#include #include #include #include #include #include #include #if 0 #include // available since Qt 4.7 #endif #include // for HOST_NAME_MAX #include // for gethostname(), getuid() #include // for getuid, getpwuid #include // for getpwuid #include "globals.h" #include "vsession.h" #include "httpxmldownloader.h" bool VSession::init(const QString& xml, const QString& baseDirPath) { this->baseDirPath_ = baseDirPath; _process = new QProcess(); return this->doc_.setContent(xml); } void VSession::addNodeWithAttribute(const QString& nodeName, const QString& value, const QString& attribute, bool replace) { QDomElement node = this->doc_.namedItem("eintrag").namedItem(nodeName).toElement(); if (replace == false || node.isNull()) { // create a new node node = this->doc_.createElement(nodeName); this->doc_.namedItem("eintrag").appendChild(node); } node.setAttribute(attribute, value); } QString VSession::icon() const { QString icon(getAttribute("icon")); if (icon.isEmpty()) { if (imgtype() == VMWARE) icon = "vmware"; else if (imgtype() == VBOX) icon = "virtualbox"; else icon = "none"; } return icon; } QString VSession::toXml() const { QDomDocument doc; doc.appendChild(doc.createElement("settings")); doc.firstChild().appendChild(doc.importNode(doc_.documentElement(), true)); QDomNode xmlNode = doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\""); doc.insertBefore(xmlNode, doc.firstChild()); return doc.toString(); } QString VSession::getAttribute(const QString &nodeName, const QString &attribute) const { QDomDocument doc = this->doc_; QDomNode n = doc.namedItem("eintrag").namedItem(nodeName); return this->doc_.namedItem("eintrag").namedItem(nodeName).toElement() .attribute(attribute); } QList VSession::keywords() const { return this->keywords_; } void VSession::readKeywords() { QDomNode keywordsNode = this->doc_.namedItem("eintrag").namedItem("keywords"); for (QDomElement el(keywordsNode.firstChildElement("keyword")); !el.isNull(); el = el.nextSiblingElement("keyword")) { this->keywords_.append(el.text()); } } bool VSession::containsKeywords(const QList& keywords) const { for (int j = 0; j < keywords.length(); ++j) { bool keywordFlag = true; if (!this->shortDescription().contains(keywords[j], Qt::CaseInsensitive) && !this->description().contains(keywords[j], Qt::CaseInsensitive) && !this->getAttribute("creator", "param").contains(keywords[j], Qt::CaseInsensitive)) { keywordFlag = false; for (int i = 0; i < this->keywords().length(); ++i) { if (this->keywords()[i].contains(keywords[j], Qt::CaseInsensitive)) { keywordFlag = true; } } if (!keywordFlag) return false; } } return true; } QString VSession::getNodeText(const QString& nodeName) const { return this->doc_.namedItem(nodeName).toText().data(); } ImgType VSession::imgtype() const { QString s(getAttribute("virtualmachine")); if (s.compare("vmware") == 0) { return VMWARE; } else if (s.compare("virtualbox") == 0 || s.compare("vbox") == 0) { return VBOX; } else { return OTHER; } } bool VSession::isActive() const { QString value(getAttribute("active")); if (value.compare("false") == 0) { return false; } else if (value.count("/") == 1) { // try to interpret value as date range // [YYYY-MM-DD]/[YYYY-MM-DD] // eg. "1970-01-01/1971-01-01" from Jan 1st 1970 till Jan 1st 1971 // "/1971-01-01" till Jan 1st 1971 // "1970-01-01/" from Jan 1st 1970 // "/" allways // note: invalid dates are treated as empty dates QStringList list(value.split("/")); QString from(list.value(0)); QString till(list.value(1)); QDate fromDate(QDate::fromString(from, Qt::ISODate)); QDate tillDate(QDate::fromString(till, Qt::ISODate)); QDate today(QDate::currentDate()); if (fromDate.isValid() && fromDate > today) { // fromDate is in the future if (debugMode) qDebug() << "Not active. Reason: fromDate is in the future"; return false; } if (tillDate.isValid() && tillDate < today) { // tillDate is in the past if (debugMode) qDebug() << "Not active. Reason: tillDate is in the past"; return false; } } if (!pool.isEmpty()) { QStringList pools = getAttribute("pools").split("\\s*,\\s*"); if (!pools.isEmpty() && !pools.contains(pool)) { // pools does not contain pool if (debugMode) qDebug() << "Not active. Reason: vsession is not part of active env"; return false; } } return true; } bool VSession::isLocked() const { // default to false return getAttribute("locked").compare("true") == 0; } bool VSession::isValid() const { // default to false return QFile::exists(QString(this->baseDirPath_).append("/").append(getAttribute("image_name"))); } int VSession::priority() const { return getAttribute("priority").toInt(); } void VSession::addUserAndHostname() { QString username(getpwuid(geteuid())->pw_name); this->addNodeWithAttribute("username", username); // Qt >= 4.7 has // QString hostname(QHostInfo::localHostName()); char hname[HOST_NAME_MAX + 1]; gethostname(hname, HOST_NAME_MAX); QString hostname(hname); this->addNodeWithAttribute("hostname", hostname); QString image(this->getAttribute("image_name")); if (QFileInfo(image).isRelative()) { // make path to image absolute this->addNodeWithAttribute("image_path", this->baseDirPath_ + "/" + image); } else { this->addNodeWithAttribute("image_path", image); } // insert computername as the first child of // bootpgm needs computername within the first 500 bytes QDomElement computername(doc_.createElement("computername")); computername.setAttribute("param", hostname); this->doc_.namedItem("eintrag").insertBefore(computername, QDomNode()); } void VSession::mergePoolXml() { QDomDocument doc; QString poolXmlFile = etcPath + "/vmchooser-" + pool + ".xml"; QFile file(poolXmlFile); if (!file.open(QIODevice::ReadOnly)) { return; } if (!doc.setContent(&file)) { file.close(); return; } file.close(); for (QDomElement envNode(doc.firstChildElement("environment")); !envNode.isNull(); envNode = envNode.nextSiblingElement()) { if (envNode.attribute("param") != pool) continue; for (QDomElement typeNode(envNode.firstChildElement()); !typeNode.isNull(); typeNode = typeNode.nextSiblingElement()) { QString type = typeNode.nodeName(); if (type != "shared_folders" && type != "printers" && type != "scanners") continue; QDomElement destinationNode = this->doc_.namedItem("eintrag").namedItem(type).toElement(); if (destinationNode.isNull()) { // create new node destinationNode = this->doc_.createElement(type); this->doc_.namedItem("eintrag").appendChild(destinationNode); } for (QDomElement el(typeNode.firstChildElement()); !el.isNull(); el = el.nextSiblingElement()) { destinationNode.appendChild(this->doc_.importNode(el, true)); } } } } bool VSession::run() const { if (debugMode) { qDebug() << "Sarting session " << this->getAttribute("short_description", "param") << " ..."; } QString command = getAttribute("command"); if (!command.isEmpty()) { return QProcess::startDetached(command); } VSession session = *this; session.addUserAndHostname(); session.mergePoolXml(); // write xml to temporary file QTemporaryFile tmpfile(QDir::tempPath() + "/vmchooser-XXXXXX.xml"); if (!tmpfile.open() || tmpfile.write(session.toXml().toUtf8()) == -1) { return false; } tmpfile.close(); tmpfile.setAutoRemove(false); _process->start(runVmScript, QStringList(tmpfile.fileName())); QObject::connect(_process, SIGNAL(finished(int, QProcess::ExitStatus)), QApplication::instance(), SLOT(quit())); if (_process->state() == QProcess::Starting || QProcess::Running) return true; else return false; } int VSession::type() const { return Session::VSESSION; } QList VSession::readXmlFile(const QString& filepath) { QList retval; QDomDocument doc; QFile file(filepath); QFile backup_file(xml_filename); if (!file.open(QIODevice::ReadOnly)) { if (debugMode) { qDebug() << "Cannot read file: " << file.fileName(); } return retval; } if (!doc.setContent(&file)) { if (debugMode) { qDebug() << "XML file not valid: " << file.fileName(); } file.close(); // try to use backup file if (!backup_file.open(QIODevice::ReadOnly)) { if (debugMode) { qDebug() << "Cannot read backup file " << xml_filename << " either"; } return retval; } if (!doc.setContent(&backup_file)) { if (debugMode) { qDebug() << "XML file not valid: " << backup_file.fileName(); } backup_file.close(); return retval; } if (debugMode) { qDebug() << "Used backup file " << xml_filename; } backup_file.close(); } else { file.close(); // file is valid --> create backup file QFile::remove(xml_filename); QFile::rename(filepath, xml_filename); if (!QFile::setPermissions(xml_filename, QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) { if (debugMode) { qDebug() << "Could not change permissions of file: " << news_backup_filename; } } } QString dirName(QFileInfo(xml_filename).dir().absolutePath()); QDomElement settingsNode = doc.firstChildElement("settings"); for (QDomElement el(settingsNode.firstChildElement("eintrag")); !el.isNull(); el = el.nextSiblingElement("eintrag")) { QDomDocument dummy; dummy.appendChild(dummy.importNode(el, true)); VSession* e = new VSession; if (e->init(dummy.toString(), dirName)) { e->readKeywords(); retval.append(e); } } return retval; } bool VSession::operator<(const Session& other) const { int p0 = this->priority(); int p1 = other.priority(); if (p0 < p1) return true; if (p0 == p1) { QString d0 = this->shortDescription(); QString d1 = other.shortDescription(); return d0.localeAwareCompare(d1) < 0; } return false; }