/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not,
* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
*
* Description:
*
*/
#include <QString>
#include <QStringList>
#include <QDebug>
#include <QFile>
#include <QIODevice>
#include <QTextStream>
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
#include <QRegExp>
#include <iostream>
using namespace std;
#define RESOURCE_DIRECTORY_RESOURCE "\\\\resource\\\\apps\\\\"
#define _s(a) QString::fromLatin1(a)
const char *FINGERPRINT = "/* xqsreg.exe fingerprint */";
QString appName;
QString uid3;
QString configurationFileName;
QString configurationFile;
QString resourceFileName;
QString embeddable;
QString hidden;
QString epocRoot()
{
QString test=QDir::root().absolutePath() ;
qDebug() << QString::fromLatin1("epocroot=") + test;
return test;
}
QString canonizePath(const QString& origPath)
{
// Since current path gets appended almost always anyway, use it as default
// for nonexisting paths.
static QString defaultPath;
if (defaultPath.isEmpty()) {
QFileInfo fi(QString::fromLatin1("."));
defaultPath = fi.canonicalFilePath();
}
// Prepend epocroot to any paths beginning with "/epoc32/"
QString resultPath = QDir::fromNativeSeparators(origPath);
if (resultPath.startsWith(QString::fromLatin1("/epoc32/"), Qt::CaseInsensitive))
resultPath = QDir::fromNativeSeparators(epocRoot()) + resultPath.mid(1);
QFileInfo fi(resultPath);
if(fi.isDir()) {
resultPath = fi.canonicalFilePath();
} else {
resultPath = fi.canonicalPath();
}
resultPath = QDir::cleanPath(resultPath);
if (resultPath.isEmpty())
resultPath = defaultPath;
return resultPath;
}
bool checkIfPatched(const QString &rssContent)
{
return rssContent.contains(_s(FINGERPRINT));
}
int parseProperties(const QStringList ¶ms)
{
int paramCount = params.size();
if (paramCount < 5) {
fprintf(stderr, "Warning: invalid parameters!\n");
fprintf(stderr, "Usage: xqsreg <application name> <application uid> <conf_file.xml> <resource file name> [embeddable] [hidden]");
return 1;
}
appName = params[1];
uid3=params[2];
configurationFileName=params[3];
configurationFile = QDir::fromNativeSeparators(canonizePath(QString::fromLatin1(".")) + QString::fromLatin1("/") + configurationFileName);
resourceFileName=params[4];
embeddable = QString::fromLatin1("KAppNotEmbeddable");
hidden = QString::fromLatin1("KAppNotHidden");
if (paramCount >= 6) {
if(!params[5].compare(QString::fromLatin1("embeddable"), Qt::CaseInsensitive)) {
embeddable = QString::fromLatin1("KAppEmbeddable");
} else if(!params[5].compare(QString::fromLatin1("hidden"), Qt::CaseInsensitive)) {
hidden = QString::fromLatin1("KAppIsHidden");
}
}
if (paramCount == 7) {
if(!params[6].compare(QString::fromLatin1("embeddable"), Qt::CaseInsensitive)) {
embeddable = QString::fromLatin1("KAppEmbeddable");
} else if(!params[6].compare(QString::fromLatin1("hidden"), Qt::CaseInsensitive)) {
hidden = QString::fromLatin1("KAppIsHidden");
}
}
return 0;
}
int populateBeforeRegInfo(QTextStream& t)
{
t << endl << endl;
t << FINGERPRINT << endl;
/* t << "// ============================================================================" << endl;
t << "// * Generated by xqrs on " << QDateTime::currentDateTime().toString() << endl;
t << "// * This file is generated by xqrs and should not be modified by the" << endl;
t << "// * user." << endl;
t << "// ============================================================================" << endl;
t << endl; */
t << "#include <xqserviceipcconst.h>" << endl;
t << "STRUCT SERVICE_CONFIGURATION {LTEXT xmldata;}" << endl;
t << "STRUCT SERVICE_CONFIGURATION_ARRAY {STRUCT service_configuration_array[];}" << endl;
t << endl;
/* t << "UID2 " << "KUidAppRegistrationResourceFile" << endl;
t << "UID3 " << uid3 << endl << endl; */
return 0;
}
int populateInsideRegInfo(QTextStream& t)
{
t << endl << endl;
/* t << "\tapp_file=\"" << appName << "\";" << endl;
t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << appName << "\";" << endl;
t << endl;*/
t << "\t" << "embeddability = " << embeddable << ";" << endl;
t << "\t" << "hidden = " << hidden << ";" << endl;
t << "\t" << "newfile = KAppDoesNotSupportNewFile;" << endl;
t << "\t" << "service_list =" << endl;
t << "\t\t" << "{" << endl;
t << "\t\t" << "SERVICE_INFO" << endl;
t << "\t\t\t" << "{" << endl;
t << "\t\t\t" << "uid = KXQServiceUid;" << endl;
t << "\t\t\t" << "datatype_list = {};" << endl;
t << "\t\t\t" << "opaque_data = r_service_configuration_reg;" << endl;
t << "\t\t\t" << "}" << endl;
t << "\t\t" << "};" << endl;
return 0;
}
int populateAfterRegInfo(QTextStream& t)
{
t << endl << endl;
t << "RESOURCE SERVICE_CONFIGURATION_ARRAY r_service_configuration_reg" << endl;
t << "\t{" << endl;
t << "\t\tservice_configuration_array=" << endl;
t << "\t\t\t{" << endl;
QFile cf(configurationFile);
int err = 0;
QByteArray escapedQuotationMark = QByteArray("\\\"");
if (cf.open(QIODevice::ReadOnly | QIODevice::Text)) {
QByteArray xmlConf;
xmlConf = cf.readAll();
xmlConf = xmlConf.replace("\"","\\\"");
if (xmlConf.count()) {
QByteArray xml = xmlConf.simplified();
for (int n=0;;n++) {
int splitCount = 255;
if (xml.size() > 255 && (xml.mid(254, 2) == escapedQuotationMark)) {
splitCount = 254;
}
QByteArray split = xml.left(splitCount);
if (!split.count()) {
break;
}
if (n) {
t << "\t\t\t\t," << endl;
}
t << "\t\t\t\tSERVICE_CONFIGURATION" << endl;
t << "\t\t\t\t{" << endl;
t << "\t\t\t\txmldata = \"" << split <<"\";" << endl;
t << "\t\t\t\t}" << endl;
xml = xml.mid(splitCount);
}
}
} else {
fprintf(stderr, "Error: Cannot open %s file for reading.", qPrintable(configurationFile));
err = 1;
}
t << endl;
t << "\t\t\t};" << endl;
t << "\t}" << endl;
return err;
}
int runXQSRegGenerator(QStringList params)
{
QFile ftR(resourceFileName);
QString fileContent(_s(""));
if ( ftR.open(QIODevice::ReadOnly | QIODevice::Text) ) {
QTextStream t(&ftR);
fileContent = t.readAll(); // let's hope file won't be too big ;)
ftR.close();
} else {
fprintf(stderr, "Error: file %s not found.\n", qPrintable(resourceFileName));
return 1;
}
if (checkIfPatched(fileContent)) {
fprintf(stderr, "Warning: matched xqsreg.exe fingerprint in resource file %s. Skipping rewriting action.\n", qPrintable(configurationFile));
return 0;
}
QRegExp qr(_s("RESOURCE\\s+APP_REGISTRATION_INFO\\s+[{]"));
int pos = qr.indexIn(fileContent, 0);
QString beforeRegistrationInfo;
QString insideRegistrationInfo;
QString afterRegistrationInfo;
QTextStream tsBeforeRegistrationInfo(&beforeRegistrationInfo);
QTextStream tsInsideRegistrationInfo(&insideRegistrationInfo);
QTextStream tsAfterRegistrationInfo(&afterRegistrationInfo);
if (populateBeforeRegInfo(tsBeforeRegistrationInfo)) {
return 1;
}
if (populateInsideRegInfo(tsInsideRegistrationInfo)) {
return 1;
}
if (populateAfterRegInfo(tsAfterRegistrationInfo)) {
return 1;
}
if (pos != -1) {
fileContent.insert(pos, beforeRegistrationInfo);
pos += qr.matchedLength() + beforeRegistrationInfo.size();
fileContent.insert(pos, insideRegistrationInfo);
fileContent.append(afterRegistrationInfo);
} else {
fprintf(stderr, "Error: RESOURCE APP_REGISTRATION_INFO not found in: %s.", qPrintable(configurationFile));
return 1;
}
QFile ft(resourceFileName);
if(ft.open(QIODevice::WriteOnly)) {
QTextStream t(&ft);
t << fileContent;
} else {
fprintf(stderr, "Error: cannot open file %s for writing.", qPrintable(configurationFile));
return 1;
}
ft.close();
return 0;
}
int main(int argc, char *argv[])
{
QStringList params;
for (int i=0 ; i < argc ; i++) {
params << QString::fromLatin1(argv[i]);
//printf("par%d=%s\n",i,argv[i]);
}
int err = parseProperties(params);
if (err == 0) {
err = runXQSRegGenerator(params);
}
return err;
}