#include "config.h" #include #include #include #include #include #include #include #include #include #include // available since Qt 4.7 #include // for getuid() #include // for getuid(), getpwuid() #include // for getpwuid() #include "globals.h" #include "vsession.h" #include "sessionsiconholder.h" #include "userldapdata.h" static QProcess _process; bool VSession::init(const QDomElement& xml) { QDomElement settingsNode = this->doc_.createElement("settings"); this->doc_.appendChild(settingsNode); eintrag_ = this->doc_.importNode(xml, true).toElement(); return !settingsNode.appendChild(eintrag_).isNull() && !settingsNode.isNull(); } void VSession::addNodeWithAttribute(const QString& nodeName, const QString& value, const QString& attribute, bool replace) { QDomElement node = eintrag_.firstChildElement(nodeName); if (replace == false || node.isNull()) { // create a new node node = this->doc_.createElement(nodeName); eintrag_.appendChild(node); } node.setAttribute(attribute, value); } QIcon VSession::icon() const { QString icon(getAttribute("icon")); SessionsIconHolder *iconHolder = SessionsIconHolder::get(); if (icon.startsWith("http://") || icon.startsWith("https://")) { // try to load icon from url QIcon url_icon(iconHolder->getIcon(QUrl(icon))); if (!url_icon.isNull()) { return url_icon; } } if (!icon.isEmpty()) { QIcon res_icon(iconHolder->getIcon(icon)); if (!res_icon.isNull()) { return res_icon; } } // Everything failed, try to guess the OS QString os(getAttribute("os", "param").toLower()); if (!os.isEmpty()) { QIcon osi = iconHolder->getIcon(os); if (!osi.isNull()) return osi; // These match vmware guestOS keywords mostly, extend for vbox... if (os == "dos") return iconHolder->getIcon("dos"); if (os.startsWith("windows7")) return iconHolder->getIcon("win7"); if (os.startsWith("win31")) return iconHolder->getIcon("win311"); if (os.startsWith("windows8")) return iconHolder->getIcon("win8"); if (os.startsWith("win2000")) return iconHolder->getIcon("win2000"); if (os.startsWith("winxp")) return iconHolder->getIcon("winxp"); if (os.startsWith("debian")) return iconHolder->getIcon("debian"); if (os.startsWith("ubuntu")) return iconHolder->getIcon("ubuntu"); if (os.startsWith("win")) return iconHolder->getIcon("windows"); if (os.contains("linux")) return iconHolder->getIcon("linux"); } // TODO: Maybe parse title of entry for an OS guess? // Fallback to generic virtualizer icon if (imgtype() == VMWARE) return iconHolder->getIcon("vmware"); if (imgtype() == VBOX) return iconHolder->getIcon("virtualbox"); return QIcon(); } QString VSession::toXml() const { QDomDocument doc(doc_); QDomNode xmlNode = doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\""); doc.insertBefore(xmlNode, doc.firstChild()); QString image(this->getAttribute("image_name")); QDomElement path = doc.firstChildElement("settings") .firstChildElement("eintrag") .appendChild(doc.createElement("image_path")) .toElement(); if (QFileInfo(image).isRelative()) { // make path to image absolute path.setAttribute("param", Config::get(Config::BASEDIR) + "/" + image); } else { path.setAttribute("param", image); } return doc.toString(); } QString VSession::getAttribute(const QString &nodeName, const QString &attribute) const { QDomNode n = eintrag_.firstChildElement(nodeName); return eintrag_.firstChildElement(nodeName).attribute(attribute); } QList VSession::keywords() const { return this->keywords_; } void VSession::readKeywords() { QDomNode keywordsNode = 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) { if (!this->shortDescription().contains(keywords[j], Qt::CaseInsensitive) && !this->description().contains(keywords[j], Qt::CaseInsensitive) && !this->getAttribute("creator", "param").contains(keywords[j], Qt::CaseInsensitive)) { bool match = false; for (int i = 0; i < this->keywords().length(); ++i) { if (this->keywords()[i].contains(keywords[j], Qt::CaseInsensitive)) { match = true; break; } } if (!match) 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")); // Is disabled completely if (value.compare("false") == 0) { if (g_debugMode) qDebug() << "'" << shortDescription() << "' not active. Reason: active == false"; return false; } // Check for date range 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 (g_debugMode) qDebug() << "'" << shortDescription() << "' not active. Reason: fromDate is in the future"; return false; } if (tillDate.isValid() && tillDate < today) { // tillDate is in the past if (g_debugMode) qDebug() << "'" << shortDescription() << "' not active. Reason: tillDate is in the past"; return false; } } // Filter by LDAP data if (!UserLdapData::isEmpty()) { QDomElement el(eintrag_.namedItem("filters").firstChildElement("filter")); if (!el.isNull()) { for (; !el.isNull(); el = el.nextSiblingElement("filter")) { if (el.attribute("type") != "LDAP") continue; if (UserLdapData::isAllowed(el.firstChildElement("key").text(), el.firstChildElement("value").text())) return true; } return false; } } return true; } bool VSession::isLocked() const { // default to false return getAttribute("locked").compare("true") == 0; } bool VSession::isValid() const { return !getAttribute("image_name").isEmpty(); } int VSession::priority() const { int prio = getAttribute("priority").toInt(); if (g_templateHandling == TEMPLATES_BUMP && isTemplate()) { prio -= 500; } if (g_forLocationHandling != LOCATION_IGNORE && isForLocation()) { prio -= 1000; } return prio; } bool VSession::run() const { if (_process.state() != QProcess::NotRunning) { qDebug() << "Cannot start vsession while old one is still running"; return false; } if (g_debugMode) { qDebug() << "Sarting session " << this->getAttribute("short_description", "param") << " ..."; } if (g_noVtx && is64Bit()) { QMessageBox::warning(nullptr, QObject::trUtf8("Warning"), QObject::trUtf8("The selected session is based on a 64 bit operating system," " but this computer doesn't seem to support this (VT-x/AMD-V not" " supported by CPU, or disabled in BIOS). You will probably get an" " error message while the virtualizer is initializing.")); } QString command = getAttribute("command"); if (!command.isEmpty()) { return QProcess::startDetached(command); } // write xml to temporary file QTemporaryFile tmpfile(QDir::tempPath() + "/vmchooser-XXXXXX.xml"); if (!tmpfile.open() || tmpfile.write(this->toXml().toUtf8()) == -1) { qDebug() << "Error writing xml to file" << tmpfile.fileName(); return false; } // Docs say we should call fileName() before closing to prevent deletion QString tmpFileName = tmpfile.fileName(); tmpfile.setAutoRemove(false); tmpfile.close(); QObject::connect(&_process, QOverload::of(&QProcess::finished), QApplication::instance(), &QCoreApplication::quit); _process.start(Config::get(Config::RUNSCRIPT), QStringList(tmpFileName)); _process.waitForStarted(10); if (_process.state() == QProcess::Starting || _process.state() == QProcess::Running) return true; else return false; } int VSession::type() const { return Session::VSESSION; } QList VSession::readXmlFile(const QString& filepath) { QList sessionList; QDomDocument doc; QFile file(filepath); QFile backup_file(TEMP_PATH_XML_LIST); if (!file.open(QIODevice::ReadOnly)) { if (g_debugMode) { qDebug() << "Cannot read file: " << file.fileName(); } return sessionList; } if (!doc.setContent(&file)) { if (g_debugMode) { qDebug() << "XML file not valid: " << file.fileName(); } file.close(); // try to use backup file if (!backup_file.open(QIODevice::ReadOnly)) { if (g_debugMode) { qDebug() << "Cannot read backup file " << TEMP_PATH_XML_LIST << " either"; } return sessionList; } if (!doc.setContent(&backup_file)) { if (g_debugMode) { qDebug() << "XML file not valid: " << backup_file.fileName(); } backup_file.close(); return sessionList; } if (g_debugMode) { qDebug() << "Used backup file " << TEMP_PATH_XML_LIST; } backup_file.close(); } else { file.close(); // file is valid --> create backup file QFile::remove(TEMP_PATH_XML_LIST); QFile::rename(filepath, TEMP_PATH_XML_LIST); if (!QFile::setPermissions(TEMP_PATH_XML_LIST, QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) { if (g_debugMode) { qDebug() << "Could not change permissions of file: " << TEMP_PATH_NEWS; } } } UserLdapData::init(); QDomElement settingsNode = doc.firstChildElement("settings"); for (QDomElement el(settingsNode.firstChildElement("eintrag")); !el.isNull(); el = el.nextSiblingElement("eintrag")) { VSession* e = new VSession; if (e->init(el) && e->isActive()) { e->readKeywords(); sessionList.append(e); } else { delete e; } } return sessionList; } bool VSession::is64Bit() const { ImgType type = imgtype(); return (type == VMWARE && getAttribute("os").endsWith("-64")) || (type == VBOX && getAttribute("os").endsWith("_64")); // TODO: qemu-kvm, ... } QVariant VSession::foregroundRole() const { if (!g_noVtx || !is64Bit()) return Session::foregroundRole(); return QColor(180, 180, 180); } 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; }