/* * updaterconfig.cpp by Matthias Braun * * Copyright (C) 2002 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include "updaterglobals.h" #include "updaterconfig.h" #include "download.h" /* node = node to get info from defv = DEFault Value returns the string */ csString LoadVar(iDocumentNode* node, csString defv) { if (!node) { printf("Warning: Using default value"); return defv; } csString str = node->GetContentsValue(); if (str == "") { printf("Warning: Using default value for %s\n" , node->GetValue() ); return defv; } return str; } namespace updater { Config::Config (iDocumentNode* node) { config = node; skipVerCheckThisSession = false; } Config::~Config () { } bool Config::Initialize() { activeMirror = 0; arrayMirror = 0; // Parse config and add missing xml elements if (!config || strcmp(config->GetValue(), "config") != 0) psupdaterengine->CriticalError("Invalid XML config node! updaterconfig.xml is corrupted!"); //Get temp file tempfile = LoadVar( config->GetNode ("temp") , "download.tmp"); // Get whole_zip setting iDocumentNode* node = config->GetNode ("whole_zips"); if(node) wholeZips = node->GetContentsValueAsInt() ? true : false; else { printf("Warning, using default value for whole_zips (false)\n"); wholeZips = false; } // Get zip_sync setting node = config->GetNode ("zip_sync"); if(node) zipSync = node->GetContentsValueAsInt(); else { printf("Warning, using default value for zip_sync (0)\n"); zipSync = 0; } // % whole zip setting node = config->GetNode ("precent_wholezip"); if(node) zipPre = node->GetContentsValueAsInt(); else { printf("Warning, using default value for precent_wholezip (100)\n"); zipPre = 100; } // Get updater_MD5 setting node = config->GetNode ("updater_MD5"); if(node) updaterMD5 = node->GetContentsValueAsInt() ? true : false; else { printf("Warning, using default value for updater_MD5 (true)\n"); updaterMD5 = true; } // Get Windows updater path node = config->GetNode ("updaterWin"); if(node) updaterWin = node->GetContentsValue(); // Get the Mac updater path node = config->GetNode ("updaterMac"); if(node) updaterMac = node->GetContentsValue(); // Get the linux updater path node = config->GetNode ("updaterLinux"); if(node) updaterLinux = node->GetContentsValue(); if(updaterWin == "" || updaterMac == "" || updaterLinux == "") printf("Warning, can't find paths for win or mac or linux updater application! (Server only)\n"); //Get config files csRef configsNode = config->GetNode ("configs"); if (configsNode != NULL) { csRef node = configsNode->GetNodes(); while(node->HasNext()) { csRef cnode = node->Next(); if (!strcmp(cnode->GetValue(),"config")) { const char* ext = cnode->GetAttributeValue("ext"); if (ext) { configExt.Push(csString(ext)); } const char* file = cnode->GetAttributeValue("file"); if (file) { configFiles.Push(csString(file)); } continue; } } } else { Error1("Config extensions node () not found (Server only)\n"); } //Get the sortings files csRef sortNode = config->GetNode ("sortings"); if (sortNode != NULL) { csRef node = sortNode->GetNodes(); while(node->HasNext()) { csRef snode = node->Next(); if (!strcmp(snode->GetValue(),"sort")) { SortEntry* sortEntry = new SortEntry; const char* ext = snode->GetAttributeValue("ext"); if (ext) { sortEntry->file = false; sortEntry->ext= ext; } const char* file = snode->GetAttributeValue("file"); if (file) { sortEntry->file = true; sortEntry->path = file; // Rename file? const char* dest_file = snode->GetAttributeValue("dest_file"); if (dest_file) sortEntry->destFile = dest_file; } const char* to = snode->GetAttributeValue("to"); if (to) { sortEntry->to = to; } sortings.Push(sortEntry); continue; } } } else { Error1("File sort rules node () not found (Server only)\n"); } //Get mirrors activeMirror = (unsigned int)-1; csRef mirrorNode = config->GetNode ("mirrors"); if (mirrorNode != NULL) { csRef node = mirrorNode->GetNodes(); while(node->HasNext()) { csRef mnode = node->Next(); if (!strcmp(mnode->GetValue(),"mirror")) { Mirror* mirror = new Mirror; mirror->id = mnode->GetAttributeValueAsInt("id"); if(mirror->id == -1) { Error1("Attempted to use Last resort feature, although this isn't finished. Skipping\n"); delete mirror; continue; } mirror->name = mnode->GetAttributeValue("name"); mirror->baseURL = mnode->GetAttributeValue("url"); mirror->repositoryFile = mnode->GetAttributeValue("repository"); mirror->versionFile = mnode->GetAttributeValue("versioninfo"); mirror->filesDirectory = mnode->GetAttributeValue("files"); mirror->passphrase = mnode->GetAttributeValue("passphrase"); mirror->noVersion = mnode->GetAttributeValueAsBool("noversion"); if (mirror->repositoryFile.IsEmpty()) mirror->repositoryFile = "repository.zip"; if (mirror->versionFile.IsEmpty()) mirror->versionFile = "version.dat"; mirrors.Push(mirror); continue; } } } else { Error1("Mirror node not found (CRITICAL ERROR!)\n"); } if(activeMirror == -1) { Notify1(LOG_ANY, "Randomizing mirrors.. "); srand(time(NULL)); // if only one server then use it if (mirrors.Length()==1) activeMirror = 1; // else randomize between mirrors-1. skip last resort, always last mirror else activeMirror = (unsigned int)(rand() % (mirrors.Length()-1))+1; Notify2(LOG_ANY,"Using mirror %d\n",activeMirror); // Mirror SHOULD exist if(!GetMirror()) { psupdaterengine->CriticalError("Check numbering on mirrors, jump occurred"); return false; } } //Get proxy settings csRef proxynode = config->GetNode ("proxy"); if (proxynode != NULL) { //Proxy active? csRef node = proxynode->GetNode ("active"); if (node != NULL) proxy.active = node->GetContentsValueAsInt() ? true : false; //Get proxy host node = proxynode->GetNode ("host"); if (node != NULL) proxy.host = node->GetContentsValue(); //Get proxy port node = proxynode->GetNode ("port"); if (node != NULL) proxy.port = node->GetContentsValueAsInt(); } else { printf("Proxy node not found (Not needed if not used)\n"); } //Get omitings csRef omitNode = config->GetNode ("omit"); if (omitNode != NULL) { csRef node = omitNode->GetNodes(); while(node->HasNext()) { csRef onode = node->Next(); if (!strcmp(onode->GetValue(),"file")) { fileOmits.Push(onode->GetAttributeValue("path")); continue; } if (!strcmp(onode->GetValue(),"dir")) { dirOmits.Push(onode->GetAttributeValue("path")); continue; } } } else { printf("File omitting rules node () not found (Server only)\n"); } //Get system files csRef sysNode = config->GetNode ("system"); if (sysNode != NULL) { csRef node = sysNode->GetNodes(); while(node->HasNext()) { csRef snode = node->Next(); if (!strcmp(snode->GetValue(),"file")) { systemFiles.Push(snode->GetAttributeValue("path")); continue; } } } else { printf("System file rules () not found! Without this the updater may remove it's own critical files! Please fix!\n"); } //Get linux system files csRef linuxSysNode = config->GetNode ("linux_system"); if (linuxSysNode != NULL) { csRef node = linuxSysNode->GetNodes(); while(node->HasNext()) { csRef snode = node->Next(); if (!strcmp(snode->GetValue(),"file")) { linuxSystemFiles.Push(snode->GetAttributeValue("path")); continue; } } } //Get critical files csRef crtNode = config->GetNode ("critical"); if (crtNode != NULL) { csRef node = crtNode->GetNodes(); while(node->HasNext()) { csRef cnode = node->Next(); if (!strcmp(cnode->GetValue(),"file")) { criticalFiles.Push(cnode->GetAttributeValue("path")); continue; } } } else { printf("Critical files () not found (Server only)\n"); } if (mirrors.Length() == 0) { psupdaterengine->OutToScreen("No mirrors found! Can't continue!"); return false; } if (activeMirror == 0 && mirrors.Length() > 0) { SetMirror(1); } return true; } void Config::SetBackupMode(bool value) { csRef node = config->GetNode("backup"); if (!node) return; node->RemoveNodes(); node->CreateNodeBefore(CS_NODE_TEXT)->SetValueAsInt(value); } bool Config::MakeBackup() const { csRef node = config->GetNode("backup"); return node && node->GetContentsValueAsInt(); } void Config::ModuleSetup (csArray& modules) const { modules.Empty(); csRef modulenode = config->GetNode ("modules"); if (!modulenode) return; csRef it = modulenode->GetNodes(); while (it->HasNext()) { csRef node = it->Next(); if (node->GetType() != CS_NODE_ELEMENT) continue; if (strcmp (node->GetValue(), "module") != 0) { fprintf (stderr, "Warning: Expected module node got '%s'.\n", node->GetValue()); continue; } const char* module = node->GetContentsValue(); if (module) modules.Push(module); } if (GetIncludeOS()) modules.Push(GetOSModule()); } void Config::SetIncludeOS(bool value) { csRef autonode = config->GetNode("autoinclude_os"); if (!autonode) return; autonode->RemoveNodes(); autonode->CreateNodeBefore(CS_NODE_TEXT)->SetValueAsInt(value); psupdaterengine->GetUpdater()->RefreshModules(); } bool Config::GetIncludeOS() const { csRef autonode = config->GetNode("autoinclude_os"); return autonode && autonode->GetContentsValueAsInt(); } bool Config::IsUsingModule(const char* name) { csRef modulenode = config->GetNode("modules"); if (!modulenode) return false; csRef it = modulenode->GetNodes(); while (it->HasNext()) { csRef node = it->Next(); if (node->GetType() != CS_NODE_ELEMENT) continue; if (strcmp (node->GetValue(), "module") != 0) { fprintf (stderr, "Warning: Expected module node got '%s'.\n", node->GetValue()); continue; } csString module(node->GetContentsValue()); if (module == name) return true; } return false; } void Config::AddModule(const char* name) { csRef modulenode = config->GetNode("modules"); if (!modulenode) return; // Check if it's already included first if (IsUsingModule(name)) return; // Add the new node csRef node = modulenode->CreateNodeBefore(CS_NODE_ELEMENT); node->SetValue("module"); node->CreateNodeBefore(CS_NODE_TEXT)->SetValue(name); psupdaterengine->GetUpdater()->RefreshModules(); } void Config::RemoveModule(const char* name) { csRef modulenode = config->GetNode("modules"); if (!modulenode) return; csRef it = modulenode->GetNodes(); while (it->HasNext()) { csRef node = it->Next(); if (node->GetType() != CS_NODE_ELEMENT || strcmp(node->GetValue(), "module") != 0) continue; csString module(node->GetContentsValue()); if (module == name) { csRef parent = node->GetParent(); parent->RemoveNode(node); } } psupdaterengine->GetUpdater()->RefreshModules(); } void Config::SetModuleUse(const char* name, bool use) { if (use) AddModule(name); else RemoveModule(name); } void Config::SetProxy(bool active, const char* host, int port) { proxy.active = active; proxy.host = host; proxy.port = port; csRef proxynode = config->GetNode("proxy"); if (proxynode) { proxynode->RemoveNodes(); csRef node1 = proxynode->CreateNodeBefore(CS_NODE_ELEMENT); node1->SetValue("active"); node1->CreateNodeBefore(CS_NODE_TEXT)->SetValueAsInt(active); proxynode->CreateNodeBefore(CS_NODE_COMMENT)->SetValue(" Set to 1 for activation "); csRef node2 = proxynode->CreateNodeBefore(CS_NODE_ELEMENT); node2->SetValue("host"); node2->CreateNodeBefore(CS_NODE_TEXT)->SetValue(host); proxynode->CreateNodeBefore(CS_NODE_COMMENT)->SetValue(" The host WITHOUT http:// or any other prefix "); csRef node3 = proxynode->CreateNodeBefore(CS_NODE_ELEMENT); node3->SetValue("port"); node3->CreateNodeBefore(CS_NODE_TEXT)->SetValueAsInt(port); proxynode->CreateNodeBefore(CS_NODE_COMMENT)->SetValue(" The port to use "); } else { printf("Proxy node not found; cannot save.\n"); } psupdaterengine->GetUpdater()->GetDownloader()->SetProxy( active, host, port ); } const char* Config::GetOSModule() { #ifdef CS_PLATFORM_WIN32 return "win32"; #elif defined CS_PLATFORM_MACOSX return "macosx"; #elif defined CS_PLATFORM_UNIX && (SIZEOF_LONG == 4) return "linux32"; #elif defined CS_PLATFORM_UNIX && (SIZEOF_LONG == 8) return "linux64"; #else return "other_os"; #endif } const char* Config::GetOSName() { #ifdef CS_PLATFORM_WIN32 return "Windows"; #elif defined CS_PLATFORM_MACOSX return "Mac OS X"; #elif defined CS_PLATFORM_UNIX && (SIZEOF_LONG == 4) return "32bit Linux"; #elif defined CS_PLATFORM_UNIX && (SIZEOF_LONG == 8) return "64bit Linux"; #else return "Unknown OS"; #endif } bool Config::ShouldIgnoreFile(const char* file) { // Check if we should ignore this file or not for (size_t i = 0; i < fileOmits.Length();i++) { csString str = fileOmits.Get(i); if (str == file) { return true; } else { if (str.GetAt(0) == '*') { //If we have a * as the first char, see if the string contains str if (strstr(file,str.Slice(1,str.Length()))) { return true; } } } } return false; } bool Config::ShouldIgnoreDir(const char* dir) { // Check if we should ignore this file or not for (size_t i = 0; i < dirOmits.Length();i++) { csString str = dirOmits.Get(i); if (str == dir) { return true; } else { if (str.GetAt(0) == '*') { //If we have a * as the first char, see if the string contains str if (strstr(dir,str.Slice(1,str.Length()))) { return true; } } } } return false; } Mirror* Config::GetMirror(unsigned int id) { for (size_t i = 0;i < mirrors.Length(); i++) { Mirror* mirror = mirrors.Get(i); if (mirror->id == id) return mirror; } return NULL; } Mirror* Config::GetMirror() { return GetMirror(activeMirror); } csString Config::GetCurrentRepositoryURL() { Mirror* mirror = GetMirror(); csString url; url = mirror->baseURL; url += mirror->repositoryFile; return url; } csString Config::GetCurrentVersionURL() { Mirror* mirror = GetMirror(); csString url; url = mirror->baseURL; url += mirror->versionFile; return url; } csString Config::GetCurrentFilesDirectory() { Mirror* mirror = GetMirror(); csString url; url = mirror->baseURL; url += mirror->filesDirectory; // We assume no trailing / symbol. if(url.GetAt(url.Length() - 1) == '/') url.Truncate(url.Length() - 1); return url; } void Config::SetNextMirror() { size_t newArrM = arrayMirror; if (mirrors.Length() == 0) return; if ( (unsigned int)mirrors.Length() < (newArrM +1)) newArrM = 1; else newArrM++; Mirror* mirror = mirrors.Get(newArrM-1); arrayMirror = newArrM; activeMirror = mirror->id; } void Config::SetMirror(unsigned int id) { Mirror* mirror = NULL; size_t i; for (i = 0;i < mirrors.Length(); i++) { mirror = mirrors.Get(i); if (mirror->id == id) break; } if (!mirror) { printf("Tried to set non-existing mirror!\n"); return; } arrayMirror = i; activeMirror = id; } void Config::ResetFailures() { for (size_t i = 0;i < mirrors.Length();i++) { Mirror* mirror = mirrors.Get(i); mirror->working = true; } } bool Config::SetNextWorkingMirror() { size_t newArrM = arrayMirror; for (size_t i = 0; i < mirrors.Length();i++) { if(mirrors.Get(i)->GetID() == (unsigned int)-1) continue; if ((unsigned int)mirrors.Length() < (newArrM +1)) newArrM = 1; else newArrM++; Mirror* mirror = mirrors.Get(newArrM-1); if (mirror->working) { arrayMirror = newArrM; activeMirror = mirror->id; return true; } } // Didn't find any working mirror return false; } bool Config::IsConfig(const char* file) { //First see if the ext is right csString filename = file; csString ext = filename.Slice(filename.FindLast('.') +1,filename.Length()); size_t i; for(i = 0;i < configExt.Length();i++) { if (ext == configExt[i]) return true; } // Check if the file is in the config file list for (i = 0; i < configFiles.Length();i++) { csString str = configFiles.Get(i); if (str == filename) { return true; } else { if (str.GetAt(0) == '*') { //If we have a * as the first char, see if the string contains str if (strstr(filename,str.Slice(1,str.Length()))) { return true; } } } } return false; } const csString Config::GetSortedPath(const char* path,const char* currentModule) { csString pathStr = path; csString filename = pathStr.Slice(pathStr.FindLast('/') +1,pathStr.Length()); csString pathOnly = pathStr.Slice(0,pathStr.Length() - filename.Length()); csString ext = filename.Slice(filename.FindLast('.') +1,filename.Length()); for (size_t i = 0; i < sortings.Length(); i++) { SortEntry* entry = sortings[i]; if (entry->file) { if (entry->path == path) { if(entry->destFile != "") return entry->to + "/" + pathOnly + entry->destFile; else return entry->to + "/" + pathStr; } } else { if (strstr(path,entry->ext)) return entry->to + "/" + pathStr; } } return csString(currentModule) + "/" + path; } bool Config::HasCustomSortDest(const char* path) { for (size_t i = 0; i < sortings.Length(); i++) { SortEntry* entry = sortings[i]; if (entry->file) { if (entry->path == path) { if(entry->destFile != "") return true; } } } return false; } bool Config::CheckCriticalFiles() { bool missing = false; for (size_t i = 0; i < criticalFiles.Length();i++) { csString file = criticalFiles.Get(i); if(!fopen(file,"r")) { printf("WARNING! Critical file %s not found!\n",file.GetData()); missing = true; } } return !missing; } } // end of namespace updater