ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/AE/Installer/trunk/source/installer.cpp
(Generate patch)

Comparing AE/Installer/trunk/source/installer.cpp (file contents):
Revision 487 by iritscen, Wed Dec 30 01:51:38 2009 UTC vs.
Revision 502 by iritscen, Mon Mar 22 16:51:50 2010 UTC

# Line 9 | Line 9
9   // TODO: Load credits from text resource file
10   // TODO: Clear mod info fields when mod is de-selected
11  
12 < #define DEBUG
13 <
12 > //#define DEBUG
13 > #ifdef WIN32
14 > //#include <windows.h>
15 > #define popen _popen
16 > #endif
17   #include "boost/date_time/gregorian/gregorian.hpp"
18   #include "boost/date_time/date_parsing.hpp"
19   #include "boost/date_time/posix_time/posix_time.hpp"
# Line 299 | Line 302 | int globalizeData(void)
302                  /* On Mac only, set the current GDF to the AE GDF by writing to Oni's global preferences file (thankfully a standard OS X ".plist" XML file).
303                   Tests for presence of prefs with [ -f ] before doing anything so it doesn't create a partial prefs file -- just in case user has never
304                   run Oni before :-p */
305 <                string fullAEpath = escapePath(system_complete(".").parent_path().parent_path().string()); // get full path for edition/
305 >                string fullAEpath = escapePath(system_complete(".").parent_path().parent_path().string()); // get full path for Edition/ (Oni wants the folder that *contains* the GDF)
306                  char prefsCommand[300] = "[ -f ~/Library/Preferences/com.godgames.oni.plist ] && defaults write com.godgames.oni RetailInstallationPath -string '";
307 <                strcat(prefsCommand, fullAEpath.c_str()); // get path of Edition/ folder (Oni wants the folder that *contains* the GDF)
307 >                strcat(prefsCommand, fullAEpath.c_str());
308                  strcat(prefsCommand, "'"); // path string is enclosed in single quotes to avoid the need to escape UNIX-unfriendly characters
309                  system(prefsCommand);
310   #endif
# Line 323 | Line 326 | int globalizeData(void)
326   vector<ModPackage> getPackages(string packageDir)
327   {
328          vector<ModPackage> packages;
329 +        ModPackage package;
330          packages.reserve(256);
331          fstream file;
332          string filename = "\0";
# Line 334 | Line 338 | vector<ModPackage> getPackages(string pa
338                  {
339                          file.open((dir_itr->path().string() + "/" + MODINFO_CFG).c_str());
340                          
341 <                        if(!file.fail())
341 >                        if (!file.fail())
342                          {
343 <                                //would prefer to push a pointer to a package, but this will do for now
344 <                                packages.push_back(fileToModPackage(file));
343 >                                package = fileToModPackage(file);
344 >                                if (package.installerVersion.compare(INSTALLER_VERSION) < 1)  // if mod requires newer version of the Installer, we won't add it to the list
345 >                                {
346 > #ifdef WIN32
347 >                                        if (!package.platform.compare("Windows") || !package.platform.compare("Both")) // don't show package if it's not for the right OS
348 > #else
349 >                                        if (!package.platform.compare("Macintosh") || !package.platform.compare("Both"))
350 > #endif
351 >                                                packages.push_back(package);
352 >                                }
353                          }      
354                          file.close();
355                          file.clear();
# Line 364 | Line 376 | ModPackage fileToModPackage(fstream &fil
376           */
377          ModPackage package;
378          string line;
379 <        static string NameOfMod = "NameOfMod";  //used for comparing to the current token...
380 <        //I could have done it in reverse (*iter).compare("ModString") or  
381 <        static string ARROW = "->";                             //did something like "ModString".compare(*iter), and it would have been
382 <        static string ModString = "ModString";  //functionably the same.
379 >        static string AEInstallVersion = "AEInstallVersion"; // used for comparing to the current token...
380 >        static string NameOfMod = "NameOfMod";
381 >        static string ARROW = "->";
382 >        static string ModString = "ModString";
383 >        static string Platform = "Platform";
384          static string HasOnis = "HasOnis";
385          static string HasDeltas = "HasDeltas";
386          static string HasBSL = "HasBSL";
# Line 377 | Line 390 | ModPackage fileToModPackage(fstream &fil
390          static string GlobalNeeded = "GlobalNeeded";
391          static string Category = "Category";
392          static string Creator = "Creator";
393 <        while (! file.eof() )
393 >        while (!file.eof())
394          {
395 <                getline (file,line);
395 >                getline(file,line);
396                  vector<string> tokens;
397                  vector<string>::iterator iter;
398 <                tokenize(line, tokens);                                 //string to vector of "words"
399 <                if (tokens.capacity() >= 3) {                   //make sure they are using enough stuff
400 <                        iter = tokens.begin();                          //what word we are on, starts at first word
401 <                        /* TODO: Get this "required Installer version" code working
402 <                         if (!AEInstallVersion.compare(*iter))
403 <                         If mod is too old, skip this mod.
404 <                         */
405 <                        /*else*/if (!NameOfMod.compare(*iter))  {       //if it contains the name
406 <                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     // iterates through the words, ends if it reaches the end of the line or a "//" comment
407 <                                        if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) {                 // ignores "->" and "NameOfMod"
398 >                tokenize(line, tokens);
399 >                if (tokens.capacity() >= 3)
400 >                {
401 >                        iter = tokens.begin();
402 >
403 >                        if (!AEInstallVersion.compare(*iter))
404 >                        {
405 >                                iter++; iter++;
406 >                                package.installerVersion = *iter;
407 >                        }
408 >                        else if (!NameOfMod.compare(*iter))
409 >                        {
410 >                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) // iterates through the words, ends if it reaches the end of the line or a "//" comment
411 >                                {
412 >                                        if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) // ignores "->" and "NameOfMod"
413                                                  package.name += *iter + " ";
396                                        }
414                                  }
398                                
415                          }
416 <                        else if (!ModString.compare(*iter)) {
416 >                        else if (!ModString.compare(*iter))
417 >                        {
418                                  iter++; iter++;
419                                  package.modStringName = *iter;
420                                  iter++;
421                                  package.modStringVersion = atoi((*iter).c_str());
422                          }
423 <                        else if (!HasOnis.compare(*iter)) {
423 >                        else if (!Platform.compare(*iter))
424 >                        {
425 >                                iter++; iter++;
426 >                                package.platform = *iter;
427 >                        }
428 >                        else if (!HasOnis.compare(*iter))
429 >                        {
430                                  iter++; iter++;  
431 <                                if ( boost::iequals(*iter, "Yes")) package.hasOnis = 1;
431 >                                if (boost::iequals(*iter, "Yes")) package.hasOnis = 1;
432                          }      
433 <                        else if (!HasBSL.compare(*iter)) {
434 <                                if(toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.hasBSL = true;
435 <                                else if ( boost::iequals(*iter, "Addon")) package.hasAddon = true;
433 >                        else if (!HasBSL.compare(*iter))
434 >                        {
435 >                                iter++; iter++;
436 >                                if (toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.hasBSL = true;
437 >                                else if (boost::iequals(*iter, "Addon")) package.hasAddon = true;
438                          }
439 <                        else if (!HasDeltas.compare(*iter)) {
439 >                        else if (!HasDeltas.compare(*iter))
440 >                        {
441                                  iter++; iter++;  
442 <                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDeltas = 1;
442 >                                if (toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.hasDeltas = 1;
443                          }
444 <                        else if (!HasDats.compare(*iter)) {
444 >                        else if (!HasDats.compare(*iter))
445 >                        {
446                                  iter++; iter++;  
447 <                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDats = 1;
447 >                                if (toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.hasDats = 1;
448                          }
449 <                        else if (!IsEngine.compare(*iter)) {
449 >                        else if (!IsEngine.compare(*iter))
450 >                        {
451                                  iter++; iter++;  
452 <                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.isEngine = 1;
452 >                                if (toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.isEngine = 1;
453                          }
454 <                        else if (!GlobalNeeded.compare(*iter)) {
454 >                        else if (!GlobalNeeded.compare(*iter))
455 >                        {
456                                  iter++; iter++;  
457 <                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.globalNeeded = 1;
458 <                                else if (toupper((*iter)[0]) + toupper((*iter)[1]) == 'N' + 'O') package.globalNeeded = 1; // only place where checking for "No" is important atm.
457 >                                if (toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.globalNeeded = 1;
458 >                                else if (toupper((*iter)[0]) == 'N' && toupper((*iter)[1]) == 'O') package.globalNeeded = 1; // only place where checking for "No" is important atm
459                          }
460 <                        else if (!Category.compare(*iter))  {  
461 <                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     // iterates through the words, ends if it reaches end of line or a "//" comment
462 <                                        if (ARROW.compare(*iter) && Category.compare(*iter)) {                  // ignores "->" and "Category"
460 >                        else if (!Category.compare(*iter))
461 >                        {      
462 >                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++)
463 >                                {
464 >                                        if (ARROW.compare(*iter) && Category.compare(*iter)) // ignores "->" and "Category"
465                                                  package.category += *iter + " ";
435                                        }
466                                  }
467                          }
468 <                        else if (!Creator.compare(*iter))  {    //if it contains the name
469 <                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     // iterates through the words, ends if it reaches end of line or a "//" comment
470 <                                        if (ARROW.compare(*iter) && Creator.compare(*iter)) {                   // ignores "->" and "Creator"
468 >                        else if (!Creator.compare(*iter))
469 >                        {
470 >                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++)
471 >                                {
472 >                                        if (ARROW.compare(*iter) && Creator.compare(*iter)) // ignores "->" and "Creator"
473                                                  package.creator += *iter + " ";
442                                        }
474                                  }
475                          }
476 <                        else if (!Readme.compare(*iter))  {     //if it contains the name
477 <                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     // iterates through the words, ends if it reaches end of line or a "//" comment
478 <                                        if (ARROW.compare(*iter) && Readme.compare(*iter)) {                    // ignores "->" and "Readme"
479 <                                                if(!(*iter).compare("\\n")) package.readme += '\n';
476 >                        else if (!Readme.compare(*iter))
477 >                        {
478 >                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++)
479 >                                {
480 >                                        if (ARROW.compare(*iter) && Readme.compare(*iter)) // ignores "->" and "Readme"
481 >                                        {
482 >                                                if (!(*iter).compare("\\n")) package.readme += '\n';
483                                                  else package.readme += *iter + " ";
484                                          }
485                                  }
486                          }
487                  }
454                
488          }
489  
490          return package;
# Line 936 | Line 969 | bool ReadInstallInfoCfg(fstream *fileHan
969          
970          while (getline(*fileHandler, line))
971          {
972 +                StripNewlines(&line);
973                  tokenize(line, tokens);
974                  iter = tokens.begin();
975                  
# Line 1139 | Line 1173 | bool ProcessInstallerUpdate(Install_info
1173          string popenCommand = "../updates/" + strEUFN + "/install/";
1174   #ifdef WIN32
1175          // TODO: Fill in Windows equivalent of code below :-3
1176 +        popenCommand = "replace_installer.bat";
1177   #else
1178          // We can't just use '~' to mean "the home directory" because we need to check the path in C...
1179          // ...so we actually get the current user's shortname and manually construct the path to home
# Line 1160 | Line 1195 | bool ProcessInstallerUpdate(Install_info
1195   #endif
1196          file.close();
1197          file.clear();
1198 + #ifdef WIN32
1199 +        system(popenCommand.c_str());
1200 + #else
1201          popen(popenCommand.c_str(), "r");
1202 <        
1202 > #endif
1203          return true; // returning 'true' tells the Installer to quit itself ASAP so it can be replaced by the process that is now running
1204   }
1205  
# Line 1192 | Line 1230 | bool ProcessAEUpdate(Install_info_cfg *c
1230          
1231          // TODO: Fill in Windows equivalent of code below
1232   #ifdef WIN32
1233 <        string strTrashDir = "%RECYCLE%";
1233 >        string strTrashDir = "Trash\\";
1234   #else
1235          FILE *fUserName = NULL;
1236          char chrUserName[32];
# Line 1237 | Line 1275 | bool ProcessAEUpdate(Install_info_cfg *c
1275                                  needNewTrashDir = true;
1276                  }
1277          }
1278 <        
1278 > #ifndef WIN32
1279          if (!*installerJustUpdated || needNewTrashDir) // prepare a new directory for deleted files to go to
1280          {
1281                  tm tmStartTime = to_tm(startTime);
# Line 1245 | Line 1283 | bool ProcessAEUpdate(Install_info_cfg *c
1283                                            boost::lexical_cast<string>(tmStartTime.tm_min) + "-" + boost::lexical_cast<string>(tmStartTime.tm_sec) + "/";
1284                  create_directory(strTrashDir);
1285          }
1286 + #endif
1287          file.close();
1288          file.clear();
1289  
# Line 1279 | Line 1318 | bool ProcessAEUpdate(Install_info_cfg *c
1318                  if (exists(strPathToEUFNInstall + strWinGUI))
1319                  {
1320                          if (exists((path)strWinGUI))
1321 <                                rename((path)strWinGUI, (path)strcat(strTrashDir, strWinGUI));
1321 >                                rename((path)strWinGUI, (path)(strTrashDir + strWinGUI));
1322                          if (exists(strWinGUILang))
1323 <                                rename((path)strWinGUILang, (path)strcat(strTrashDir, strWinGUILang));
1323 >                                rename((path)strWinGUILang, (path)(strTrashDir + strWinGUILang));
1324                          rename((path)(strPathToEUFNInstall + strWinGUI), (path)strWinGUI);
1325                          rename((path)(strPathToEUFNInstall + strWinGUILang), (path)strWinGUILang);
1326                  }
# Line 1320 | Line 1359 | bool ProcessAEUpdate(Install_info_cfg *c
1359                                  curPos = thePath.find("/", lastPos);
1360                                  aParentPath = aParentPath + "/";
1361                          }
1362 + #ifndef WIN32
1363                          rename((path)("../" + thePath), (path)(strTrashDir + thePath));
1364 + #else
1365 +                        remove((path)("../" + thePath));
1366 + #endif
1367                  }
1368          }
1369          
# Line 1343 | Line 1386 | bool ProcessAEUpdate(Install_info_cfg *c
1386                                  matchFound = true;
1387                                  if (iter1->modStringVersion > iter2->modStringVersion)
1388                                  {
1389 + #ifndef WIN32
1390                                          rename((path)(strPathToPackages + iter2->modStringName), (path)(strTrashDir + iter2->modStringName));
1391 + #else
1392 +                                        remove((path)(strPathToPackages + iter2->modStringName));
1393 + #endif
1394                                          rename((path)(strPathToEUFNPackages + iter1->modStringName), (path)(strPathToPackages + iter1->modStringName));
1395                                  }
1396                          }
# Line 1454 | Line 1501 | void tokenize(const string& str, vector<
1501          }
1502   }
1503  
1504 + /* StripNewlines() gets rids of any linebreaks that come from text returned by getline(); \
1505 + |  getline() should be stripping those out, but Windows CR/LF files seem to be sneaking   |
1506 + \  some extra return characters into strings in the ReadInstallInfoCfg() function.               */
1507 + void StripNewlines(string *theLine)
1508 + {
1509 +        int deleteFromHere = 0;
1510 +        deleteFromHere = theLine->find("\r");
1511 +        if (deleteFromHere > 0)
1512 +                theLine->erase(deleteFromHere, theLine->size());
1513 + }
1514 +
1515   void clearOldDats(void) {
1516          directory_iterator end_iter_gdf;
1517          for ( directory_iterator dir_itr_gdf( "../GameDataFolder" );
# Line 1568 | Line 1626 | ModPackage::ModPackage()
1626          name = "";
1627          modStringName = "";
1628          modStringVersion = 0;
1629 +        platform = "Both";
1630          hasOnis = false;
1631          hasDeltas = false;
1632          hasBSL = false;
# Line 1579 | Line 1638 | ModPackage::ModPackage()
1638          readme = "";
1639          globalNeeded = true;
1640   }
1641 <
1641 > #ifndef WIN32
1642   void Sleep(int ms)
1643   {
1644          sleep(ms / 1000);
1645   }
1646 <
1646 > #endif
1647   #ifdef WIN32
1648  
1649   void RedirectIOToConsole()

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)