--- /dev/null
+// Copyright (C) 2012 by Konrad Rosenbaum <konrad@silmor.de>
+// protected under the GNU LGPL version 3 or at your option any newer.
+// See COPYING.LGPL file that comes with this distribution.
+//
+
+#include "metafile.h"
+#include "../gnupg/include/host2net.h"
+#include <QFile>
+#include <QFileInfo>
+#include <QProcess>
+#include <QDir>
+
+#include <QtXml>
+
+static const QString slocalOS =
+#ifdef Q_OS_LINUX
+ "linux"
+#elif defined(Q_OS_WIN)
+ "windows"
+#else
+#warning "Unknown OS, please extend me"
+ "unknown"
+#endif
+;
+
+static const QString slocalCPU =
+#ifdef Q_PROCESSOR_X86_32
+ "x86"
+#elif defined(Q_PROCESSOR_X86_64)
+ "x86-64"
+#else
+#warning "Unknown CPU, please extend me"
+ "unknown"
+#endif
+;
+
+static inline bool matchLocalOS(const QString &os)
+{
+ if(os==slocalOS || os=="all")return true;
+#ifdef AURORA_INSTGEN_BUILD
+ if(os=="any")return true;
+#endif
+ return false;
+}
+
+static inline bool matchLocalCPU(const QString &cpu)
+{
+ if(cpu==slocalCPU || cpu=="all")return true;
+#ifdef AURORA_INSTGEN_BUILD
+ if(cpu=="any")return true;
+#endif
+ return false;
+}
+
+static inline bool matchLocal(const QString &os,const QString &cpu)
+{
+ return matchLocalOS(os)&&matchLocalCPU(cpu);
+}
+
+#ifdef AURORA_INSTGEN_BUILD
+static inline QString createArchiveName(const QString&name,const QString&os, const QString&cpu)
+{
+ //shortcut
+ if(!name.contains('*'))return name;
+ //create the replacement for *: os-cpu; any is replaced with the actual os/cpu
+ QString ast;
+ if(os=="any")ast=slocalOS;
+ else ast=os;
+ ast+="-";
+ if(cpu=="any")ast+=slocalCPU;
+ else ast+=cpu;
+ return QString(name).replace('*',ast);
+}
+
+static inline QString resolveDir(QString dir,const QString&base=".")
+{
+ if(dir.isEmpty())dir=".";
+ //stage 1: resolve pipe
+ if(dir.startsWith("|")){
+ QProcess prc;
+ prc.start(dir.mid(1),QIODevice::ReadOnly);
+ if(!prc.waitForFinished()){
+ qDebug()<<"Error: Failed to resolve directory externally.";
+ qDebug()<<" Command:"<<dir;
+ qDebug()<<" Result:"<<prc.exitCode()<<prc.readAllStandardError().trimmed();
+ return QString();
+ }
+ dir=QString::fromLocal8Bit(prc.readAllStandardOutput()).trimmed();
+ }
+ //stage 2: if absolute - use it, otherwise combine
+ if(!QFileInfo(dir).isAbsolute() && !base.isEmpty())dir=base+"/"+dir;
+ //stage 3: normalize
+ const bool slash=dir.startsWith('/');
+ QStringList dl;
+ for(const QString&dc:dir.replace('\\','/').split("/",QString::SkipEmptyParts)){
+ if(dc==".")continue;
+ if(dc==".."){
+ if(dl.size()==0)dl<<dc;
+ else if(dl[dl.size()-1]=="..")dl<<dc;
+ else dl.takeLast();
+ }else dl<<dc;
+ }
+ if(slash)dir="/";else dir="";
+ for(const QString&dc:dl){
+ if(dir.size()>0 && dir!="/")dir+="/";
+ dir+=dc;
+ }
+ if(dir.size()==0)dir=".";
+ //done
+ return dir;
+}
+#endif
+
+QString MetaFile::localPlatform()
+{
+ return slocalOS+"-"+slocalCPU;
+}
+
+Archive::Archive(const QDomElement& ael)
+#ifdef AURORA_INSTGEN_BUILD
+ :misSource(false)
+#endif
+{
+ mName=ael.attribute("name");
+ msha1=ael.attribute("sha1sum");
+ mos=ael.attribute("os");
+ mcpu=ael.attribute("cpu");
+}
+
+MetaFile::MetaFile(const QString& fname)
+{
+ QFile fd(fname);
+ if(!fd.open(QIODevice::ReadOnly)){
+ qDebug()<<"Unable to open Meta File";
+ return;
+ }
+ QDomDocument doc;
+ if(!doc.setContent(&fd)){
+ qDebug()<<"Meta File is not XML";
+ return;
+ }
+ QDomElement root=doc.documentElement();
+ mValid=root.tagName()=="AuroraInfo";
+ QDomElement el=doc.elementsByTagName("CurrentVersion").at(0).toElement();
+ mBuilt=QDateTime::fromString(el.attribute("buildDate"),Qt::ISODate);
+ mInstalled=QDateTime::fromString(el.attribute("installDate"),Qt::ISODate);
+ mVersionH=el.attribute("version");
+ mVersionM=el.attribute("mrv");
+ el=doc.elementsByTagName("Settings").at(0).toElement();
+ mBaseUrl=el.attribute("baseurl");
+ mIndexFile=el.attribute("indexfile");
+ mPollInterval=el.attribute("pollinterval","-1").toInt();
+ //go through archive sources
+ QDomNodeList nl;
+#ifdef AURORA_INSTGEN_BUILD
+ nl=doc.elementsByTagName("ArchiveSource");
+ for(int i=0;i<nl.size();i++){
+ el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ if(!el.hasAttribute("name")){
+ qDebug()<<"Warning: ArchiveSource at line"<<el.lineNumber()<<"column"<<el.columnNumber()<<"has no name, skipping it.";
+ continue;
+ }
+ const QString aname=el.attribute("name");
+ const QString buildbase=resolveDir(el.attribute("buildbase","."));
+ const QString zipbase=el.attribute("zipbase",".");
+ qDebug()<<"Found Archive Source"<<aname<<"; buildbase:"<<buildbase<<"; zipbase:"<<zipbase;
+ //go through platforms, look for match
+ QDomNodeList nlp=el.elementsByTagName("Platform");
+ for(int j=0;j<nlp.size();j++){
+ QDomElement elp=nlp.at(j).toElement();
+ if(elp.isNull())continue;
+ const QString os=elp.attribute("os","any");
+ const QString cpu=elp.attribute("cpu","any");
+ if(!matchLocal(os,cpu)){
+ qDebug()<<"Skipping OS"<<os<<"CPU"<<cpu;
+ continue;
+ }
+ qDebug()<<"Recording OS"<<os<<"CPU"<<cpu;
+ const QString pbuildbase=resolveDir(el.attribute("buildbase","."),buildbase);
+ const QString pzipbase=resolveDir(el.attribute("zipbase","."),zipbase);
+ //generate Archive object
+ mArchives.append(Archive(elp,pbuildbase,pzipbase,aname));
+ }
+ }
+#endif
+ //go through finished archives
+ nl=doc.elementsByTagName("Archive");
+ for(int i=0;i<nl.size();i++){
+ el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ if(!el.hasAttribute("name")){
+ qDebug()<<"Warning: Archive at line"<<el.lineNumber()<<"column"<<el.columnNumber()<<"has no name, skipping it.";
+ continue;
+ }
+ mArchives.append(Archive(el));
+ }
+}
+
+#ifdef AURORA_INSTGEN_BUILD
+
+bool ArchiveFile::fileMatches(QString filename) const
+{
+ return mpat.exactMatch(filename) && !mexclude.exactMatch(filename);
+}
+
+static inline QStringList listdir(const QString&dirn)
+{
+ QDir d(dirn);
+ QStringList ret;
+ for(const QFileInfo&fi:d.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot|QDir::Readable)){
+ if(fi.isFile())
+ ret.append(dirn+"/"+fi.fileName());
+ else
+ ret.append(listdir(dirn+"/"+fi.fileName()));
+ }
+ return ret;
+}
+
+QStringList ArchiveFile::getFiles() const
+{
+ //split pattern
+ QStringList ret;
+ for(const QString&c:listdir(mSource)){
+ if(mpat.exactMatch(c) && !mexclude.exactMatch(c))
+ ret.append(c);
+ }
+ return ret;
+}
+
+Archive::Archive(const QDomElement& pfel, const QString& bb, const QString& zb,const QString&nm)
+ :mBuildBase(bb),mZipBase(zb),misSource(true)
+{
+ mos=pfel.attribute("os","any");
+ mcpu=pfel.attribute("cpu","any");
+ if(nm.contains("*"))mName=createArchiveName(nm,mos,mcpu);
+ else mName=nm;
+ //files...
+ QDomNodeList nl=pfel.elementsByTagName("Files");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ //bases
+ const QString buildbase=resolveDir(el.attribute("buildbase","."),mBuildBase);
+ const QString zipbase=resolveDir(el.attribute("zipbase","."),mZipBase);
+ const QString exclude=el.attribute("exclude");
+ //files
+ for(QString fp:el.text().split("\n")){
+ fp=fp.trimmed();
+ if(fp.isEmpty())continue;
+ mFiles.append(ArchiveFile(buildbase,zipbase,fp,exclude));
+ }
+ }
+}
+
+//end of library build
+#endif
--- /dev/null
+// Copyright (C) 2013 by Konrad Rosenbaum <konrad@silmor.de>
+// protected under the GNU LGPL version 3 or at your option any newer.
+// See COPYING.LGPL file that comes with this distribution.
+//
+
+#ifndef AURORA_META_H
+#define AURORA_META_H
+
+#include <QStringList>
+#include <QDateTime>
+#include <QRegExp>
+
+class QDomElement;
+namespace AuroraUpdater {
+
+#define AURORA_INSTGEN_BUILD
+#ifdef AURORA_INSTGEN_BUILD
+
+#ifdef Q_OS_WIN
+#define CS Qt::CaseInsensitive
+#else
+#define CS Qt::CaseSensitive
+#endif
+class ArchiveFile {
+ QString mSource,mDest;
+ QRegExp mpat,mexclude;
+
+ friend class Archive;
+ ArchiveFile(QString src,QString dst,QString pat,QString excl)
+ :mSource(src.replace('\\','/')),
+ mDest(dst.replace('\\','/')),
+ mpat(pat,CS,QRegExp::WildcardUnix),
+ mexclude(excl,CS,QRegExp::WildcardUnix)
+ {}
+public:
+ ArchiveFile(){}
+ ArchiveFile(const ArchiveFile&)=default;
+
+ QString sourcePath()const{return mSource;}
+ QString destinationPath()const{return mDest;}
+ QRegExp pattern()const{return mpat;}
+ QRegExp excludePattern()const{return mexclude;}
+
+ bool fileMatches(QString filename)const;
+ QStringList getFiles()const;
+};
+#undef CS
+#endif
+
+///Description of a single Archive File
+class Archive {
+ QString mName,msha1,mos,mcpu;
+
+ friend class MetaFile;
+ ///instantiate from <Archive>
+ Archive(const QDomElement&);
+#ifdef AURORA_INSTGEN_BUILD
+ ///instantiate from <Platform> and <Files>
+ Archive(const QDomElement&,const QString&,const QString&,const QString&);
+ QString mBuildBase,mZipBase;
+ bool misSource=false;
+ QList<ArchiveFile>mFiles;
+#endif
+public:
+ Archive(){}
+ Archive(const Archive&)=default;
+
+ QString name()const{return mName;}
+
+ QString sha1sum()const{return msha1;}
+
+ QString operatingSystem()const{return mos;}
+ QString cpu()const{return mcpu;}
+
+#ifdef AURORA_INSTGEN_BUILD
+ QString buildBaseDir()const{return mBuildBase;}
+ QString zipBaseDir()const{return mZipBase;}
+ bool isSource()const{return misSource;}
+ QList<ArchiveFile>filePatterns()const{return mFiles;}
+#endif
+
+};
+
+///Encapsulates meta files: XML descriptions of how to generate and/or download packages.
+class MetaFile
+{
+ QDateTime mBuilt,mInstalled;
+ QString mVersionH,mVersionM,mBaseUrl,mIndexFile;
+ int mPollInterval=-1;
+ QList<Archive>mArchives;
+ bool mValid=false;
+public:
+ ///create empty meta file object, not recommended
+ MetaFile(){}
+ ///copies a meta file object
+ MetaFile(const MetaFile&)=default;
+ ///expects a file name and tries to read this file as an XML meta file
+ MetaFile(const QString&);
+
+ QDateTime buildTime()const{return mBuilt;}
+ QDateTime installTime()const{return mInstalled;}
+
+ QString version()const{return mVersionH;}
+ QString machineVersion()const{return mVersionM;}
+
+ QString baseUrl()const{return mBaseUrl;}
+ QString indexFile()const{return mIndexFile;}
+
+ int pollInterval()const{return mPollInterval;}
+
+ QList<Archive> archives()const{return mArchives;}
+
+ bool isValid()const{return mValid;}
+
+ static QString localPlatform();
+};
+
+//end of namespace
+};
+
+using namespace AuroraUpdater;
+
+#endif