From 7544aca77f9115764080e81c180b6df2e1666c46 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Wed, 12 Jun 2013 15:47:48 +0100 Subject: [PATCH] Bug fixes. Fixed resource paths in report being wrong, updating masterlist no longer displays command line window, settings file is now read after creation if creation is necessary, and fixed some error handling during sorting. --- src/backend/generators.h | 6 ++-- src/backend/globals.cpp | 5 +++- src/backend/globals.h | 3 ++ src/backend/helpers.cpp | 25 +++++++++++++++++ src/backend/helpers.h | 3 ++ src/backend/network.cpp | 48 ++++++++++++++++---------------- src/gui/main.cpp | 59 ++++++++++++++++++---------------------- src/installer.nsi | 26 +++++++++--------- 8 files changed, 103 insertions(+), 72 deletions(-) diff --git a/src/backend/generators.h b/src/backend/generators.h index f4bbcd59..1ff06662 100644 --- a/src/backend/generators.h +++ b/src/backend/generators.h @@ -129,11 +129,11 @@ namespace boss { node = head.append_child(); node.set_name("link"); node.append_attribute("rel").set_value("stylesheet"); - node.append_attribute("href").set_value("../resources/style.css"); + node.append_attribute("href").set_value(ToFileURL(css_path).c_str()); node = head.append_child(); node.set_name("script"); - node.append_attribute("src").set_value("../resources/polyfill.js"); + node.append_attribute("src").set_value(ToFileURL(polyfill_path).c_str()); node.text().set(" "); } @@ -448,7 +448,7 @@ namespace boss { node = body.append_child(); node.set_name("script"); - node.append_attribute("src").set_value("../resources/script.js"); + node.append_attribute("src").set_value(ToFileURL(js_path).c_str()); node.text().set(" "); } diff --git a/src/backend/globals.cpp b/src/backend/globals.cpp index 16ade454..e7d31fda 100644 --- a/src/backend/globals.cpp +++ b/src/backend/globals.cpp @@ -49,10 +49,13 @@ namespace boss { const unsigned int VERSION_PATCH = 0; //Common paths. - const boost::filesystem::path readme_path = "Docs/BOSS Readme.html"; + const boost::filesystem::path readme_path = "docs/BOSS Readme.html"; const boost::filesystem::path libespm_options_path = "resources/libespm.yaml"; const boost::filesystem::path svn_path = "resources/svn/svn.exe"; const boost::filesystem::path local_path = GetLocalAppDataPath() / "BOSS"; + const boost::filesystem::path css_path = boost::filesystem::current_path() / "resources" / "style.css"; + const boost::filesystem::path js_path = boost::filesystem::current_path() / "resources" / "script.js"; + const boost::filesystem::path polyfill_path = boost::filesystem::current_path() / "resources" / "polyfill.js"; const boost::filesystem::path settings_path = local_path / "settings.yaml"; const boost::filesystem::path log_path = local_path / "BOSSDebugLog.txt"; } diff --git a/src/backend/globals.h b/src/backend/globals.h index fa7492b3..712ff914 100644 --- a/src/backend/globals.h +++ b/src/backend/globals.h @@ -54,6 +54,9 @@ namespace boss { extern const boost::filesystem::path readme_path; extern const boost::filesystem::path settings_path; extern const boost::filesystem::path libespm_options_path; + extern const boost::filesystem::path css_path; + extern const boost::filesystem::path js_path; + extern const boost::filesystem::path polyfill_path; extern const boost::filesystem::path svn_path; extern const boost::filesystem::path log_path; } diff --git a/src/backend/helpers.cpp b/src/backend/helpers.cpp index 4db36650..e0af18ae 100644 --- a/src/backend/helpers.cpp +++ b/src/backend/helpers.cpp @@ -220,6 +220,31 @@ namespace boss { return fs::path(""); #endif } + + //Turns an absolute filesystem path into a valid file:// URL. + std::string ToFileURL(const fs::path& file) { + //URLs are UTF-8 encoded then any characters (equiv. their corresponding bytes) not in the unreserved set (equiv. their corresponding bytes) are replaced by a percentage sign followed by the hex representation of their binary value. + string unreserved = "-.0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; //Unreserved in byte value order, plus the colon character since that's allowed for drive paths. + + string url = "file://"; + for (boost::filesystem::path::const_iterator it=file.begin(), endit=file.end(); it != endit; ++it) { + string part = it->string(); + if (part == "/") //Skip exta backslash after drive path. + continue; + //String iterator is byte-by-byte, not character-by-character, which is good. + for (string::const_iterator jt=part.begin(), endjt=part.end(); jt != endjt; ++jt) { + if (!binary_search(unreserved.begin(), unreserved.end(), *jt)) + //Replace with percentage-hex value. + url += '%' + IntToHexString(*jt); + else + url += *jt; + } + url += '/'; + } + url.resize(url.length()-1); //Get rid of trailing forward slash. + + return url; + } ////////////////////////////// diff --git a/src/backend/helpers.h b/src/backend/helpers.h index df8a073f..83beeaec 100644 --- a/src/backend/helpers.h +++ b/src/backend/helpers.h @@ -66,6 +66,9 @@ namespace boss { //Get the local application data path. boost::filesystem::path GetLocalAppDataPath(); + //Turns an absolute filesystem path into a valid file:// URL. + std::string ToFileURL(const boost::filesystem::path& file); + //Version class for more robust version comparisons. class Version { private: diff --git a/src/backend/network.cpp b/src/backend/network.cpp index 27bc19df..f231a593 100644 --- a/src/backend/network.cpp +++ b/src/backend/network.cpp @@ -73,7 +73,8 @@ namespace boss { siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = consoleWrite; siStartInfo.hStdOutput = consoleWrite; - siStartInfo.dwFlags |= STARTF_USESTDHANDLES; + siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + siStartInfo.wShowWindow = SW_HIDE; const int utf16Len = MultiByteToWideChar(CP_UTF8, 0, command.c_str(), -1, NULL, 0); wchar_t * cmdLine = new wchar_t[utf16Len]; @@ -126,36 +127,37 @@ namespace boss { if (!RunCommand(command, output)) throw error(ERROR_SUBVERSION_ERROR, "Subversion could not update the masterlist. Details: " + output); - //Now test masterlist to see if it parses OK. - bool good = false; - while (!good) { + + string revision; + while (true) { try { + + //Now get the masterlist revision. + command = svn_path.string() + " info \"" + game.MasterlistPath().string() + "\""; + if (!RunCommand(command, output)) + throw error(ERROR_SUBVERSION_ERROR, "Subversion could not read the masterlist revision number. Details: " + output); + + size_t pos1 = output.rfind("Revision: "); + size_t pos2 = output.find('\n', pos1); + + revision = output.substr(pos1+10, pos2-pos1-10); + + pos1 = output.find("Last Changed Date: ", pos2); + pos2 = output.find(' ', pos1+19); + + string date = output.substr(pos1+19, pos2-pos1-19); + + //Now test masterlist to see if it parses OK. YAML::Node mlist = YAML::LoadFile(game.MasterlistPath().string()); - good = true; + + return revision + " (" + date + ")"; } catch (YAML::Exception& e) { //Roll back one revision if there's an error. - parsingErrors.push_back(e.what()); + parsingErrors.push_back("Masterlist revision " + revision + ": " + e.what()); command = svn_path.string() + " update --revision PREV \"" + game.MasterlistPath().string() + "\""; if (!RunCommand(command, output)) throw error(ERROR_SUBVERSION_ERROR, "Subversion could not update the masterlist. Details: " + output); } } - - //Now get the masterlist revision. Can either create a pipe using the Win32 API (http://msdn.microsoft.com/en-us/library/ms682499.aspx), or output to a file, read it, then delete it. - command = svn_path.string() + " info \"" + game.MasterlistPath().string() + "\""; - if (!RunCommand(command, output)) - throw error(ERROR_SUBVERSION_ERROR, "Subversion could not read the masterlist revision number. Details: " + output); - - size_t pos1 = output.rfind("Revision: "); - size_t pos2 = output.find('\n', pos1); - - string revision = output.substr(pos1+10, pos2-pos1-10); - - pos1 = output.find("Last Changed Date: ", pos2); - pos2 = output.find(' ', pos1+19); - - string date = output.substr(pos1+19, pos2-pos1-19); - - return revision + " (" + date + ")"; } } diff --git a/src/gui/main.cpp b/src/gui/main.cpp index df50ce72..3f682c54 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -79,19 +79,7 @@ bool BossGUI::OnInit() { } //Load settings. - if (fs::exists(settings_path)) { - try { - _settings = YAML::LoadFile(settings_path.string()); - } catch (YAML::ParserException& e) { - //LOG_ERROR("Error: %s", e.getString().c_str()); - wxMessageBox( - FromUTF8(format(loc::translate("Error: Settings parsing failed. %1%")) % e.what()), - translate("BOSS: Error"), - wxOK | wxICON_ERROR, - NULL); - return false; - } - } else { + if (!fs::exists(settings_path)) { try { if (!fs::exists(settings_path.parent_path())) fs::create_directory(settings_path.parent_path()); @@ -105,6 +93,19 @@ bool BossGUI::OnInit() { } GenerateDefaultSettingsFile(settings_path.string()); } + if (fs::exists(settings_path)) { + try { + _settings = YAML::LoadFile(settings_path.string()); + } catch (YAML::ParserException& e) { + //LOG_ERROR("Error: %s", e.getString().c_str()); + wxMessageBox( + FromUTF8(format(loc::translate("Error: Settings parsing failed. %1%")) % e.what()), + translate("BOSS: Error"), + wxOK | wxICON_ERROR, + NULL); + return false; + } + } //Skip logging initialisation for tester. /* if (gl_log_debug_output) @@ -327,6 +328,11 @@ void Launcher::OnClose(wxCloseEvent& event) { void Launcher::OnSortPlugins(wxCommandEvent& event) { + YAML::Node mlist, ulist; + list messages, mlist_messages, ulist_messages; + list mlist_plugins, ulist_plugins; + time_t start, end; + wxProgressDialog *progDia = new wxProgressDialog(translate("BOSS: Working..."),translate("BOSS working..."), 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME); time_t t0 = time(NULL); @@ -334,7 +340,6 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { ofstream out((local_path / "out.txt").string().c_str()); out << "Updating masterlist..." << endl; - time_t start, end; start = time(NULL); vector parsingErrors; @@ -342,13 +347,10 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { try { revision = UpdateMasterlist(_game, parsingErrors); } catch (boss::error& e) { - //LOG_ERROR("Error: %s", e.what()); - wxMessageBox( - FromUTF8(format(loc::translate("Error: Condition evaluation failed. %1%")) % e.what()), - translate("BOSS: Error"), - wxOK | wxICON_ERROR, - this); - return; + messages.push_back(boss::Message(boss::MESSAGE_ERROR, string("Masterlist update failed. Details: ") + e.what())); + } + for (vector::const_iterator it=parsingErrors.begin(), endit=parsingErrors.end(); it != endit; ++it) { + messages.push_back(boss::Message(boss::MESSAGE_ERROR, *it)); } end = time(NULL); @@ -376,10 +378,6 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { out << "Time taken to read plugins: " << (end - start) << " seconds." << endl; start = time(NULL); - YAML::Node mlist, ulist; - list messages, mlist_messages, ulist_messages; - list mlist_plugins, ulist_plugins; - if (fs::exists(_game.MasterlistPath())) { out << "Parsing masterlist..." << endl; @@ -392,6 +390,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { translate("BOSS: Error"), wxOK | wxICON_ERROR, this); + progDia->Destroy(); return; } if (mlist["globals"]) @@ -416,6 +415,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { translate("BOSS: Error"), wxOK | wxICON_ERROR, this); + progDia->Destroy(); return; } if (ulist["plugins"]) @@ -461,13 +461,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { try { it->EvalAllConditions(_game, lang); } catch (boss::error& e) { - //LOG_ERROR("Error: %s", e.what()); - wxMessageBox( - FromUTF8(format(loc::translate("Error: Condition evaluation failed. %1%")) % e.what()), - translate("BOSS: Error"), - wxOK | wxICON_ERROR, - this); - return; + messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + it->Name() + "\" contains a condition that could not be evaluated. Details: " + e.what())); } progDia->Pulse(); @@ -652,6 +646,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { translate("BOSS: Error"), wxOK | wxICON_ERROR, this); + progDia->Destroy(); return; } diff --git a/src/installer.nsi b/src/installer.nsi index 6e1ff83b..359eca62 100644 --- a/src/installer.nsi +++ b/src/installer.nsi @@ -262,14 +262,14 @@ LangString TEXT_USERFILES ${LANG_SIMPCHINESE} "BOSS的userlist和BOSS.ini文件 File "..\build\libboss64.dll" ;Now install readme files. - SetOutPath "$INSTDIR\Docs" + SetOutPath "$INSTDIR\docs" File "..\docs\BOSS API Readme.html" File "..\docs\BOSS Metadata Syntax.html" File "..\docs\BOSS Readme.html" File "..\docs\Licenses.txt" ;Now install readme images. - SetOutPath "$INSTDIR\Docs\images" + SetOutPath "$INSTDIR\docs\images" File "..\docs\images\editor.png" File "..\docs\images\main.png" File "..\docs\images\settings.png" @@ -383,19 +383,19 @@ LangString TEXT_USERFILES ${LANG_SIMPCHINESE} "BOSS的userlist和BOSS.ini文件 RMDir "$INSTDIR\API" ;Remove readme files. - Delete "$INSTDIR\Docs\BOSS API Readme.html" - Delete "$INSTDIR\Docs\BOSS Metadata Syntax.html" - Delete "$INSTDIR\Docs\BOSS Readme.html" - Delete "$INSTDIR\Docs\Licenses.txt" - RMDir "$INSTDIR\Docs" + Delete "$INSTDIR\docs\BOSS API Readme.html" + Delete "$INSTDIR\docs\BOSS Metadata Syntax.html" + Delete "$INSTDIR\docs\BOSS Readme.html" + Delete "$INSTDIR\docs\Licenses.txt" + RMDir "$INSTDIR\docs" ;Remove readme images. - Delete "$INSTDIR\Docs\images\editor.png" - Delete "$INSTDIR\Docs\images\main.png" - Delete "$INSTDIR\Docs\images\settings.png" - Delete "$INSTDIR\Docs\images\viewer-1.png" - Delete "$INSTDIR\Docs\images\viewer-2.png" - RMDir "$INSTDIR\Docs\images" + Delete "$INSTDIR\docs\images\editor.png" + Delete "$INSTDIR\docs\images\main.png" + Delete "$INSTDIR\docs\images\settings.png" + Delete "$INSTDIR\docs\images\viewer-1.png" + Delete "$INSTDIR\docs\images\viewer-2.png" + RMDir "$INSTDIR\docs\images" ;Remove resource files. Delete "$INSTDIR\resources\libespm.yaml"