void LoadCommandMap( const char* path ){ StringOutputStream strINI( 256 ); strINI << path << "shortcuts.ini"; FILE* f = fopen( strINI.c_str(), "r" ); if ( f != 0 ) { fclose( f ); globalOutputStream() << "loading custom shortcuts list from " << makeQuoted( strINI.c_str() ) << "\n"; Version version = version_parse( COMMANDS_VERSION ); Version dataVersion = { 0, 0 }; { char value[1024]; if ( read_var( strINI.c_str(), "Version", "number", value ) ) { dataVersion = version_parse( value ); } } if ( version_compatible( version, dataVersion ) ) { globalOutputStream() << "commands import: data version " << dataVersion << " is compatible with code version " << version << "\n"; ReadCommandMap visitor( strINI.c_str() ); GlobalShortcuts_foreach( visitor ); globalOutputStream() << "parsed " << Unsigned( visitor.count() ) << " custom shortcuts\n"; } else { globalOutputStream() << "commands import: data version " << dataVersion << " is not compatible with code version " << version << "\n"; } } else { globalOutputStream() << "failed to load custom shortcuts from " << makeQuoted( strINI.c_str() ) << "\n"; } }
RootXMLConstructor(const char* elementName, XMLElementParser& parser, const char* version) : m_elementName(elementName), m_parser(parser), m_version(version_parse(version)), m_compatible(false) { }
/** * Parse vendor string and fill supplied version structure `vs'. * * @returns OK if we were able to parse correctly. */ bool version_fill(const char *version, version_t *vs) { if (!version_parse(version, vs, NULL)) return FALSE; version_stamp(version, vs); /* Optional, set to 0 if missing */ return TRUE; }
XMLElementParser& pushElement(const XMLElement& element) { if(string_equal(element.name(), m_elementName.c_str())) { Version dataVersion(version_parse(element.attribute("version"))); if(version_compatible(m_version, dataVersion)) { m_compatible = true; return m_parser; } else { return m_skip; } } else { //ERROR_MESSAGE("parse error: invalid element \"" << element.name() << "\""); return *this; } }
int main() { version v1, v2, v3; char c[64]; version_init(&v1, 1, 2, 6); version_parse(&v2, "2.1.6"); version_init(&v3, 1, 2, 5); int count = version_to_string(&c[0], &v1); printf("version: %s\n", c); printf("count: %i\n", count); int b; b = version_cmp(&v1, &v2); printf("b1: %i\n", b); b = version_cmp(&v1, &v3); printf("b2: %i\n", b); b = version_cmp(&v2, &v3); printf("b3: %i\n", b); }
/** * Initialize version string. */ void G_COLD version_init(void) { time_t now; version_string = ostrdup_readonly(version_build_string()); now = tm_time(); { bool ok; const char *end; ok = version_parse(version_string, &our_version, &end); g_assert(ok); ok = version_ext_parse(end, &our_ext_version); g_assert(ok); } g_info("%s", version_string); version_stamp(version_string, &our_version); g_assert(our_version.timestamp != 0); { char buf[128]; str_bprintf(buf, sizeof(buf), "%s/%s%s (%s)", product_name(), product_version(), product_build_full(), product_date()); version_short_string = ostrdup_readonly(buf); } last_rel_version = our_version; /* struct copy */ last_dev_version = our_version; /* struct copy */ our_ext_version.version = our_version; /* struct copy */ /* * The version code is a one-byte encoding of the year/month, since * what matters is not much the version number as to the age of the * servent... The version code is transmitted in pongs via GGEP "VC". */ if (our_version.timestamp) { struct tm *tmp = localtime(&our_version.timestamp); version_code = (((tmp->tm_year + 1900 - 2000) & 0x0f) << 4) | (tmp->tm_mon + 1); } else version_code = 0; /* * The property system is not up when this is called, but we need * to set this variable correctly. */ if ( tok_is_ancient(now) || delta_time(now, our_version.timestamp) > VERSION_ANCIENT_WARN ) { *deconstify_bool(&GNET_PROPERTY(ancient_version)) = TRUE; } }
/** * Check version of servent, and if it's a gtk-gnutella more recent than we * are, record that fact and change the status bar. * * The `addr' is being passed solely for the tok_version_valid() call. * * @returns TRUE if we properly checked the version, FALSE if we got something * looking as gtk-gnutella but which failed the token-based sanity checks. */ bool version_check(const char *str, const char *token, const host_addr_t addr) { version_t their_version; version_ext_t their_version_ext; version_t *target_version; int cmp; const char *version; const char *end; bool extended; if (!version_parse(str, &their_version, &end)) return TRUE; /* Not gtk-gnutella, or unparseable */ /* * Check for extended version information (git commit ID, dirty status). */ ZERO(&their_version_ext); extended = version_ext_parse(end, &their_version_ext); if (!extended) { /* Structure could have been partially filled */ ZERO(&their_version_ext); } /* * Is their version a development one, or a release? */ if (their_version.tag == 'u') target_version = &last_dev_version; else target_version = &last_rel_version; cmp = version_cmp(target_version, &their_version); if (GNET_PROPERTY(version_debug) > 1) version_dump(str, &their_version, cmp == 0 ? "=" : cmp > 0 ? "-" : "+"); /* * Check timestamp. */ version_stamp(str, &their_version); their_version_ext.version = their_version; /* Struct copy */ if (GNET_PROPERTY(version_debug) > 3) g_debug("VERSION time=%d", (int) their_version.timestamp); /* * If version claims something older than TOKEN_START_DATE, then * there must be a token present. */ if (delta_time(their_version.timestamp, 0) >= TOKEN_START_DATE) { tok_error_t error; if (token == NULL) { if (GNET_PROPERTY(version_debug)) { g_debug("got GTKG vendor string \"%s\" without token!", str); } return FALSE; /* Can't be correct */ } error = tok_version_valid(str, token, strlen(token), addr); /* * Unfortunately, if our token has expired, we can no longer * validate the tokens of the remote peers, since they are using * a different set of keys. * * This means an expired GTKG will blindly trust well-formed remote * tokens at face value. But it's their fault, they should not run * an expired version! * --RAM, 2005-12-21 */ if (error == TOK_BAD_KEYS && tok_is_ancient(tm_time())) error = TOK_OK; /* Our keys have expired, cannot validate */ if (error != TOK_OK) { if (GNET_PROPERTY(version_debug)) { g_debug("vendor string \"%s\" [%s] has wrong token " "\"%s\": %s ", str, host_addr_to_string(addr), token, tok_strerror(error)); } return FALSE; } /* * OK, so now we know we can "trust" this version string as being * probably genuine. It makes sense to extract version information * out of it. */ } if (cmp > 0) /* We're more recent */ return TRUE; /* * If timestamp is greater and we were comparing against a stable * release, and cmp == 0, then this means an update in SVN about * a "released" version, probably alpha/beta. */ if ( cmp == 0 && (delta_time(their_version.timestamp, target_version->timestamp) > 0 || their_version.build > target_version->build) && target_version == &last_rel_version ) { if (GNET_PROPERTY(version_debug) > 3) g_debug("VERSION is a SVN update of a release"); if (version_build_cmp(&last_dev_version, &their_version) > 0) { if (GNET_PROPERTY(version_debug) > 3) g_debug("VERSION is less recent than latest dev we know"); return TRUE; } target_version = &last_dev_version; } /* * Their version is more recent, but is unstable -- only continue if * our version is also unstable. */ if (cmp < 0 && their_version.tag == 'u' && our_version.tag != 'u') return TRUE; if ( delta_time(their_version.timestamp, target_version->timestamp) < 0 || their_version.build <= target_version->build ) return TRUE; if ( delta_time(their_version.timestamp, our_version.timestamp) == 0 && their_version.build <= our_version.build ) return TRUE; /* * We found a more recent version than the last version seen. */ if (GNET_PROPERTY(version_debug) > 1) g_debug("more recent %s VERSION \"%s\"", target_version == &last_dev_version ? "dev" : "rel", str); *target_version = their_version; /* struct copy */ /* * Signal new version to user. * * Unless they run a development version, don't signal development * updates to them: they're probably not interested. */ version = version_ext_str(&their_version_ext, FALSE); /* No OS name */ g_message("more recent %s version of gtk-gnutella: %s", target_version == &last_dev_version ? "development" : "released", version); if (target_version == &last_rel_version) version_new_found(version, TRUE); else if (our_version.tag == 'u') version_new_found(version, FALSE); return TRUE; }
static int scan_file(char *filename, sci_version_t *version) { char buf[VERSION_DETECT_BUF_SIZE]; char result_string[10]; /* string-encoded result, copied from buf */ int characters_left; int state = 0; /* 'state' encodes how far we have matched the version pattern ** "n.nnn.nnn" ** ** n.nnn.nnn ** 0123456789 ** ** Since we cannot be certain that the pattern does not begin with an ** alphanumeric character, some states are ambiguous. ** The pattern is expected to be terminated with a non-alphanumeric ** character. */ exe_file_t *f = exe_open(filename); if (!f) return 1; do { int i; int accept; characters_left = exe_read(f, buf, VERSION_DETECT_BUF_SIZE); for (i = 0; i < characters_left; i++) { const char ch = buf[i]; accept = 0; /* By default, we don't like this character */ if (isalnum((unsigned char) ch)) { accept = (state != 1 && state != 5 && state != 9); } else if (ch == '.') { accept = (state == 1 || state == 5); } else if (state == 9) { result_string[9] = 0; /* terminate string */ if (!version_parse(result_string, version)) { exe_close(f); return 0; /* success! */ } /* Continue searching. */ } if (accept) result_string[state++] = ch; else state = 0; } } while (characters_left == VERSION_DETECT_BUF_SIZE); exe_close(f); return 1; /* failure */ }