/** * Free version string. */ void G_COLD version_close(void) { if (version_cmp(&our_version, &last_rel_version) < 0) g_warning("upgrade recommended: most recent released version seen: %s", version_str(&last_rel_version)); else if (version_cmp(&our_version, &last_dev_version) < 0) g_warning("upgrade possible: most recent development version seen: %s", version_str(&last_dev_version)); }
long WINAPI Win32ExceptionHandler(struct _EXCEPTION_POINTERS *pExceptInfo) { char buf[512]; MINIDUMP_EXCEPTION_INFORMATION mdei; MINIDUMP_USER_STREAM_INFORMATION mdusi; MINIDUMP_USER_STREAM mdus; bool minidump_created = false; std::string dumpfile = porting::path_user + DIR_DELIM PROJECT_NAME ".dmp"; std::string version_str(PROJECT_NAME " "); version_str += g_version_hash; HANDLE hFile = CreateFileA(dumpfile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) goto minidump_failed; if (SetEndOfFile(hFile) == FALSE) goto minidump_failed; mdei.ClientPointers = NULL; mdei.ExceptionPointers = pExceptInfo; mdei.ThreadId = GetCurrentThreadId(); mdus.Type = CommentStreamA; mdus.BufferSize = version_str.size(); mdus.Buffer = (PVOID)version_str.c_str(); mdusi.UserStreamArray = &mdus; mdusi.UserStreamCount = 1; if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, &mdusi, NULL) == FALSE) goto minidump_failed; minidump_created = true; minidump_failed: CloseHandle(hFile); DWORD excode = pExceptInfo->ExceptionRecord->ExceptionCode; _snprintf(buf, sizeof(buf), " >> === FATAL ERROR ===\n" " >> %s (Exception 0x%08X) at 0x%p\n", Win32ExceptionCodeToString(excode), excode, pExceptInfo->ExceptionRecord->ExceptionAddress); dstream << buf; if (minidump_created) dstream << " >> Saved dump to " << dumpfile << std::endl; else dstream << " >> Failed to save dump" << std::endl; return EXCEPTION_EXECUTE_HANDLER; }
void HTTP_Request::print(std::ostream& os) { os << ">" << method_to_str_dict[_method]; os << " " << _uri; if (!_query.empty()) os << "?" << _query; os << " "; os << version_str(); os << "\r\n"; for (auto& header : _headers) { os << ">"; os << header.first << ": " << header.second << "\r\n"; } os << "\r\n"; os << ">" << _body << std::endl; }
void version::load(std::istream & is) { static const char digits[] = "0123456789"; BOOST_STATIC_ASSERT(sizeof(stored_legacy_version) <= sizeof(stored_version)); stored_legacy_version legacy_version; is.read(legacy_version, std::streamsize(sizeof(legacy_version))); if(legacy_version[0] == 'i' && legacy_version[sizeof(legacy_version) - 1] == '\x1a') { for(size_t i = 0; i < size_t(boost::size(legacy_versions)); i++) { if(!memcmp(legacy_version, legacy_versions[i].name, sizeof(legacy_version))) { value = legacy_versions[i].version; bits = legacy_versions[i].bits; unicode = false; known = true; debug("known legacy version: \"" << versions[i].name << '"'); return; } } debug("unknown legacy version: \"" << std::string(legacy_version, sizeof(legacy_version)) << '"'); if(legacy_version[0] != 'i' || legacy_version[2] != '.' || legacy_version[4] != '.' || legacy_version[7] != '-' || legacy_version[8] != '-') { throw version_error(); } if(legacy_version[9] == '1' && legacy_version[10] == '6') { bits = 16; } else if(legacy_version[9] == '3' && legacy_version[10] == '2') { bits = 32; } else { throw version_error(); } std::string version_str(legacy_version, sizeof(legacy_version)); try { unsigned a = util::to_unsigned(version_str.data() + 1, 1); unsigned b = util::to_unsigned(version_str.data() + 3, 1); unsigned c = util::to_unsigned(version_str.data() + 5, 2); value = INNO_VERSION(a, b, c); } catch(boost::bad_lexical_cast) { throw version_error(); } unicode = false; known = false; return; } stored_version version; BOOST_STATIC_ASSERT(sizeof(legacy_version) <= sizeof(version)); memcpy(version, legacy_version, sizeof(legacy_version)); is.read(version + sizeof(legacy_version), std::streamsize(sizeof(version) - sizeof(legacy_version))); for(size_t i = 0; i < size_t(boost::size(versions)); i++) { if(!memcmp(version, versions[i].name, sizeof(version))) { value = versions[i].version; bits = 32; unicode = versions[i].unicode; known = true; debug("known version: \"" << versions[i].name << '"'); return; } } char * end = std::find(version, version + boost::size(version), '\0'); std::string version_str(version, end); debug("unknown version: \"" << version_str << '"'); if(version_str.find("Inno Setup") == std::string::npos) { throw version_error(); } size_t bracket = version_str.find('('); for(; bracket != std::string::npos; bracket = version_str.find('(', bracket + 1)) { if(version_str.length() - bracket < 6) { continue; } try { size_t a_start = bracket + 1; size_t a_end = version_str.find_first_not_of(digits, a_start); if(a_end == std::string::npos || version_str[a_end] != '.') { continue; } unsigned a = util::to_unsigned(version_str.data() + a_start, a_end - a_start); size_t b_start = a_end + 1; size_t b_end = version_str.find_first_not_of(digits, b_start); if(b_end == std::string::npos || version_str[b_end] != '.') { continue; } unsigned b = util::to_unsigned(version_str.data() + b_start, b_end - b_start); size_t c_start = b_end + 1; size_t c_end = version_str.find_first_not_of(digits, c_start); if(c_end == std::string::npos) { continue; } unsigned c = util::to_unsigned(version_str.data() + c_start, c_end - c_start); size_t d_start = c_end; if(version_str[d_start] == 'a') { if(d_start + 1 >= version_str.length()) { continue; } d_start++; } unsigned d = 0; if(version_str[d_start] == '.') { d_start++; size_t d_end = version_str.find_first_not_of(digits, d_start); if(d_end != std::string::npos && d_end != d_start) { d = util::to_unsigned(version_str.data() + d_start, d_end - d_start); } } value = INNO_VERSION_EXT(a, b, c, d); break; } catch(boost::bad_lexical_cast) { continue; } } if(bracket == std::string::npos) { throw version_error(); } bits = 32; unicode = (version_str.find("(u)") != std::string::npos); known = false; }
/** \brief Parse a line from a version entry. * * This function reads the header (one line), a list of logs, and then * the footer of a version entry. * * If a version exists, even if it is wrong, the function returns true. * The function returns false if the end of the file is reached. * * \param[in] s The state to read from. * * \return true if the end of the file was not yet reached when this * version was read in full. */ bool changelog_file::version::parse(state& s) { f_filename = s.get_filename(); f_line = s.get_line(); // the current line must be the header if(s.space_count() != 0) { wpkg_output::log("changelog:%1:%2: a changelog version entry must start with a valid header") .arg(f_filename) .arg(f_line) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .action("changelog"); return s.next_line(); } bool good_header(true); const std::string& header(s.last_line()); const char *h(header.c_str()); const char *start(h); // *** Package Name *** for(; !isspace(*h) && *h != '('; ++h) { if(*h == '\0') { wpkg_output::log("changelog:%1:%2: invalid header, expected the project name, version, distributions, and urgency information") .arg(f_filename) .arg(f_line) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .action("changelog"); good_header = false; break; } } if(good_header) { std::string package_name(start, h - start); if(!wpkg_util::is_package_name(package_name)) { wpkg_output::log("changelog:%1:%2: the package name %3 is not valid") .arg(f_filename) .arg(f_line) .quoted_arg(package_name) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .action("changelog"); } else { f_package = package_name; } if(!isspace(*h)) { // this is just a warning, but the user is expected to put a space // after the package name and before the version wpkg_output::log("changelog:%1:%2: the package name %3 is not followed by a space before the version information") .arg(f_filename) .arg(f_line) .quoted_arg(package_name) .level(wpkg_output::level_warning) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_header = false; } } // *** Version *** if(good_header) { for(; isspace(*h); ++h); if(*h != '(') { wpkg_output::log("changelog:%1:%2: invalid header, expected the version between parenthesis after the package name") .arg(f_filename) .arg(f_line) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_header = false; } } if(good_header) { // read the version ++h; start = h; for(; !isspace(*h) && *h != ')' && *h != '\0'; ++h); std::string version_str(start, h - start); char err[256]; if(!validate_debian_version(version_str.c_str(), err, sizeof(err))) { wpkg_output::log("control:%1:%2: %3 is not a valid Debian version") .arg(f_filename) .arg(f_line) .quoted_arg(version_str) .level(wpkg_output::level_error) .module(wpkg_output::module_changelog) .package(f_package) .action("changelog"); good_header = false; } else { f_version = version_str; } } if(good_header) { if(isspace(*h)) { for(; isspace(*h); ++h); wpkg_output::log("control:%1:%2: version %3 is not immediately followed by a closing parenthesis") .arg(f_filename) .arg(f_line) .quoted_arg(f_version) .level(wpkg_output::level_warning) .module(wpkg_output::module_changelog) .package(f_package) .action("changelog"); } if(*h != ')') { wpkg_output::log("control:%1:%2: version %3 is not followed by a closing parenthesis: ')'") .arg(f_filename) .arg(f_line) .quoted_arg(f_version) .level(wpkg_output::level_error) .module(wpkg_output::module_changelog) .package(f_package) .action("changelog"); good_header = false; } } // *** Distributions *** if(good_header) { // the first ++h is to skip the ')' from the version for(++h; isspace(*h); ++h); do { start = h; for(; !isspace(*h) && *h != '\0' && *h != ';' && *h != ','; ++h); std::string d(start, h - start); wpkg_filename::uri_filename distribution(d); if(distribution.is_absolute()) { wpkg_output::log("control:%1:%2: a distribution must be a relative path, %3 is not acceptable") .arg(f_filename) .arg(f_line) .quoted_arg(distribution) .level(wpkg_output::level_error) .module(wpkg_output::module_changelog) .package(f_package) .action("changelog"); good_header = false; } else if(distribution.segment_size() < 1) { // This happens if no distribution is specified wpkg_output::log("control:%1:%2: a distribution cannot be the empty string") .arg(f_filename) .arg(f_line) .level(wpkg_output::level_error) .module(wpkg_output::module_changelog) .package(f_package) .action("changelog"); good_header = false; } else { f_distributions.push_back(distribution.original_filename()); } for(; isspace(*h); ++h); } while(*h != '\0' && *h != ';' && *h != ','); } // We want to support more than one in source packages, that way a package // can be part of stable and unstable (because we view our distributions // as separate entities rather than complements.) //if(good_header) //{ // if(f_distributions.size() > 1) // { // wpkg_output::log("control:%1:%2: although the syntax allows for more than one distribution, we do not support more than one at this time") // .arg(f_filename) // .arg(f_line) // .level(wpkg_output::level_error) // .module(wpkg_output::module_changelog) // .package(f_package) // .action("changelog"); // good_header = false; // } //} // *** Parameters *** if(good_header) { for(; isspace(*h); ++h); if(*h != ';') { wpkg_output::log("changelog:%1:%2: invalid header, expected the list of distributions to end with ';'") .arg(f_filename) .arg(f_line) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_header = false; } else { for(++h; isspace(*h); ++h); } } while(good_header && *h != '\0') { start = h; const char *e(h); const char *equal(NULL); for(; *h != ',' && *h != '\0'; ++h) { if(!isspace(*h)) { e = h + 1; } if(*h == '=') { equal = h; } } if(equal == NULL) { wpkg_output::log("changelog:%1:%2: invalid header, parameter %3 is expected to include an equal sign (=) after the parameter name") .arg(f_filename) .arg(f_line) .quoted_arg(std::string(start, h - start)) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_header = false; } else if(start == equal) { wpkg_output::log("changelog:%1:%2: invalid header, parameter %3 is missing a name before the equal character") .arg(f_filename) .arg(f_line) .quoted_arg(std::string(start, h - start)) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_header = false; } else { std::string name(start, equal - start); if(f_parameters.find(name) != f_parameters.end()) { wpkg_output::log("changelog:%1:%2: invalid header, parameter %3 is defined twice") .arg(f_filename) .arg(f_line) .quoted_arg(name) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_header = false; } else { ++equal; std::string value(equal, e - equal); f_parameters[name] = value; } } // skip commas and spaces and repeat for next parameter for(; *h == ',' || isspace(*h); ++h); } // We got the header, now we check for the list of logs // the log::parse() function is expected to return false // once we reach the end of that list, then we must find // a footer that starts with a space and two dashes if(!s.next_line()) { wpkg_output::log("changelog:%1:%2: every changelog version entry must have at least one log and end with a valid footer") .arg(f_filename) .arg(s.get_line()) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); return false; } bool group(true); for(;;) { log l; if(!l.parse(s, group)) { break; } f_logs.push_back(l); } // we are at the end of the log stream for this version entry, // there has to be a valid footer now bool good_footer(true); if(s.space_count() != 1) { wpkg_output::log("changelog:%1:%2: a changelog version entry must end with a valid footer, which must start with exactly one space") .arg(f_filename) .arg(s.get_line()) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_footer = false; } const std::string& footer(s.last_line()); const char *f(footer.c_str()); if(good_footer) { if(f[0] != '-' || f[1] != '-' || f[2] != ' ') { wpkg_output::log("changelog:%1:%2: a changelog version entry must end with a valid footer, which must start with two dashes") .arg(f_filename) .arg(s.get_line()) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_footer = false; } } if(good_footer) { // search for two spaces to break the maintainer name/email and date f += 3; start = f; for(; f[0] != '\0' && (f[0] != ' ' || f[1] != ' '); ++f); std::string maintainer(start, f - start); // TODO: use libtld to verify email f_maintainer = maintainer; std::string date(f + 2); struct tm time_info; if(strptime(date.c_str(), "%a, %d %b %Y %H:%M:%S %z", &time_info) == NULL) { wpkg_output::log("changelog:%1:%2: the footer in this changelog version entry has an invalid date: %3") .arg(f_filename) .arg(s.get_line()) .quoted_arg(date) .level(wpkg_output::level_error) .module(wpkg_output::module_build_package) .package(f_package) .action("changelog"); good_footer = false; } else { f_date = date; } } // do not read another line in case this one is the next header return true; }