X-Git-Url: https://git.jankratochvil.net/?p=captive.git;a=blobdiff_plain;f=src%2Flibcaptive%2Fcaptivemodid%2Fcaptivemodid.c;h=3344896b1a6cb7854e9d8b16fd4cc9ba36d5bda2;hp=8aceea4e38d0140500ce9b4436ec53565740898a;hb=56c29066a72eaeb7e84a28aedc597f13f419359e;hpb=7458d2cad7f776d79163189e5a17f78095b1cb6d diff --git a/src/libcaptive/captivemodid/captivemodid.c b/src/libcaptive/captivemodid/captivemodid.c index 8aceea4..3344896 100644 --- a/src/libcaptive/captivemodid/captivemodid.c +++ b/src/libcaptive/captivemodid/captivemodid.c @@ -35,141 +35,172 @@ #include -gchar *captive_calc_md5(gconstpointer base,size_t length) +struct _CaptiveCaptivemodidObject { + GObject parent_instance; + + /* map: GINT_TO_POINTER(captive_captivemodid_module.length) -> !=NULL */ + /* No allocations needed. */ + GHashTable *module_valid_length_hash; + + /* map: (const xmlChar *)md5 -> (struct captive_captivemodid_module *) */ + /* 'key' is not allocated it is shared with: 'val'->md5 */ + /* 'val' is allocated, to be automatically freed by: captive_captivemodid_module_free() */ + GHashTable *module_md5_hash; + + /* map: (const xmlChar *)type -> (gpointer)GINT_TO_POINTER(priority) */ + /* We remove entry for module with already the best priority found, + * therefore captive_captivemodid_module_type_best_priority_lookup() will return + * 'G_MININT' afterwards. + * 'key' is not allocated - it is shared with: module_md5_hash */ + /* No allocations needed. */ + GHashTable *module_type_best_priority_hash; + + /* g_strdup()ped */ + gchar *pathname_loaded; + }; +struct _CaptiveCaptivemodidObjectClass { + GObjectClass parent_class; + }; + + +static gpointer captive_captivemodid_object_parent_class=NULL; + + +static void captive_captivemodid_object_finalize(CaptiveCaptivemodidObject *captive_captivemodid_object) { -unsigned char md5_bin[1+128/8]; /* 128 bits==16 bytes; '1+' for leading stub to prevent shorter output of BN_bn2hex() */ -BIGNUM *bignum; -char *hex; -gchar *r,*gs; + g_return_if_fail(captive_captivemodid_object!=NULL); - /* already done above */ - /* Calculate MD5 sum and convert it to hex string: */ - MD5(base,length,md5_bin+1); - md5_bin[0]=0xFF; /* stub to prevent shorter output of BN_bn2hex() */ - bignum=BN_bin2bn(md5_bin,1+128/8,NULL); - hex=BN_bn2hex(bignum); - g_assert(strlen(hex)==2*(1+128/8)); - r=g_strdup(hex+2); - OPENSSL_free(hex); - BN_free(bignum); + g_hash_table_destroy(captive_captivemodid_object->module_valid_length_hash); + g_hash_table_destroy(captive_captivemodid_object->module_md5_hash); + g_hash_table_destroy(captive_captivemodid_object->module_type_best_priority_hash); + g_free(captive_captivemodid_object->pathname_loaded); - g_assert(strlen(r)==32); - for (gs=r;*gs;gs++) { - g_assert(isxdigit(*gs)); - *gs=tolower(*gs); - g_assert(isxdigit(*gs)); - } - return r; + G_OBJECT_CLASS(captive_captivemodid_object_parent_class)->finalize((GObject *)captive_captivemodid_object); } -/* map: GINT_TO_POINTER(captive_captivemodid_module.length) -> !=NULL */ -static GHashTable *module_valid_length_hash; - -static void module_valid_length_hash_init(void) +static void captive_captivemodid_object_class_init(CaptiveCaptivemodidObjectClass *class) { - if (module_valid_length_hash) - return; - module_valid_length_hash=g_hash_table_new(g_direct_hash,g_direct_equal); +GObjectClass *gobject_class=G_OBJECT_CLASS(class); + + captive_captivemodid_object_parent_class=g_type_class_ref(g_type_parent(G_TYPE_FROM_CLASS(class))); + gobject_class->finalize=(void (*)(GObject *object))captive_captivemodid_object_finalize; } -/* map: (const xmlChar *)md5 -> (struct captive_captivemodid_module *) */ -static GHashTable *module_md5_hash; -static void module_md5_hash_init(void) +static void captive_captivemodid_module_free(struct captive_captivemodid_module *module) { - if (module_md5_hash) - return; - module_md5_hash=g_hash_table_new(g_str_hash,g_str_equal); + xmlFree((xmlChar *)module->type); + xmlFree((xmlChar *)module->md5); + xmlFree((xmlChar *)module->id); + g_free(module); } -/* map: (const xmlChar *)type -> (gpointer)GINT_TO_POINTER(priority) */ -/* We remove entry for module with already the best priority found, - * therefore captive_captivemodid_module_type_best_priority_lookup() will return - * 'G_MININT' afterwards. - */ -static GHashTable *module_type_best_priority_hash; +static void captive_captivemodid_object_init(CaptiveCaptivemodidObject *captive_captivemodid_object) +{ + captive_captivemodid_object->module_valid_length_hash=g_hash_table_new(g_direct_hash,g_direct_equal); + captive_captivemodid_object->module_md5_hash=g_hash_table_new_full(g_str_hash,g_str_equal, + NULL, /* key_destroy_func */ + (GDestroyNotify)captive_captivemodid_module_free); /* value_destroy_func */ + captive_captivemodid_object->module_type_best_priority_hash=g_hash_table_new(g_str_hash,g_str_equal); +} -static void module_type_best_priority_hash_init(void) + +GType captive_captivemodid_object_get_type(void) { - if (module_type_best_priority_hash) - return; - module_type_best_priority_hash=g_hash_table_new(g_str_hash,g_str_equal); +static GType captive_captivemodid_object_type=0; + + if (!captive_captivemodid_object_type) { +static const GTypeInfo captive_captivemodid_object_info={ + sizeof(CaptiveCaptivemodidObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)captive_captivemodid_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(CaptiveCaptivemodidObject), + 5, /* n_preallocs */ + (GInstanceInitFunc)captive_captivemodid_object_init, + }; + + captive_captivemodid_object_type=g_type_register_static(G_TYPE_OBJECT, + "CaptiveCaptivemodidObject",&captive_captivemodid_object_info,0); + } + + return captive_captivemodid_object_type; } -static void captive_captivemodid_load_module(struct captive_captivemodid_module *module) + +static void captive_captivemodid_load_module + (CaptiveCaptivemodidObject *captivemodid,struct captive_captivemodid_module *module) { struct captive_captivemodid_module *module_md5_conflict; gpointer valid_length_value_gpointer; - module_md5_hash_init(); - if ((module_md5_conflict=g_hash_table_lookup(module_md5_hash,module->md5))) { + if ((module_md5_conflict=g_hash_table_lookup(captivemodid->module_md5_hash,module->md5))) { g_warning(_("Ignoring module \"%s\" as it has MD5 conflict with: %s"), module->id,module_md5_conflict->id); return; } - g_hash_table_insert(module_md5_hash,(/* de-const */ xmlChar *)module->md5,module); + g_hash_table_insert(captivemodid->module_md5_hash,(/* de-const */ xmlChar *)module->md5,module); - module_valid_length_hash_init(); - if (!g_hash_table_lookup_extended(module_valid_length_hash,GINT_TO_POINTER(module->length), + if (!g_hash_table_lookup_extended(captivemodid->module_valid_length_hash,GINT_TO_POINTER(module->length), NULL, /* orig_key */ &valid_length_value_gpointer)) /* value */ - g_hash_table_insert(module_valid_length_hash,GINT_TO_POINTER(module->length),GINT_TO_POINTER(module->cabinet_used)); + g_hash_table_insert(captivemodid->module_valid_length_hash, + GINT_TO_POINTER(module->length),GINT_TO_POINTER(module->cabinet_used)); else { /* Conflicting 'cabinet_used' values for single 'cabinet size'? */ if (valid_length_value_gpointer && GPOINTER_TO_INT(valid_length_value_gpointer)!=module->cabinet_used) - g_hash_table_insert(module_valid_length_hash,GINT_TO_POINTER(module->length),NULL); + g_hash_table_insert(captivemodid->module_valid_length_hash,GINT_TO_POINTER(module->length),NULL); } if (strcmp((const char *)module->type,"cabinet")) { - if (module->priority>captive_captivemodid_module_type_best_priority_lookup(module->type)) { - module_type_best_priority_hash_init(); - g_hash_table_insert(module_type_best_priority_hash, + if (module->priority>captive_captivemodid_module_type_best_priority_lookup(captivemodid,module->type)) { + g_hash_table_insert(captivemodid->module_type_best_priority_hash, (/* de-const */ xmlChar *)module->type,GINT_TO_POINTER(module->priority)); } } } -gboolean captive_captivemodid_module_length_is_valid(GnomeVFSFileSize file_size) +gboolean captive_captivemodid_module_length_is_valid(CaptiveCaptivemodidObject *captivemodid,GnomeVFSFileSize file_size) { gint file_size_gint; if ((GnomeVFSFileSize)(file_size_gint=file_size)!=file_size) /* Size too big to be valid. */ return FALSE; - module_valid_length_hash_init(); - return g_hash_table_lookup_extended(module_valid_length_hash,GINT_TO_POINTER(file_size_gint), + return g_hash_table_lookup_extended(captivemodid->module_valid_length_hash,GINT_TO_POINTER(file_size_gint), NULL, /* orig_key */ NULL); /* value */ } -gint captive_captivemodid_cabinet_length_to_used(gint cabinet_length) +gint captive_captivemodid_cabinet_length_to_used(CaptiveCaptivemodidObject *captivemodid,gint cabinet_length) { gpointer valid_length_value_gpointer; - if (!g_hash_table_lookup_extended(module_valid_length_hash,GINT_TO_POINTER(cabinet_length), + if (!g_hash_table_lookup_extended(captivemodid->module_valid_length_hash,GINT_TO_POINTER(cabinet_length), NULL, /* orig_key */ &valid_length_value_gpointer)) /* value */ return 0; return GPOINTER_TO_INT(valid_length_value_gpointer); } -struct captive_captivemodid_module *captive_captivemodid_module_md5_lookup(const gchar *file_md5) +struct captive_captivemodid_module *captive_captivemodid_module_md5_lookup + (CaptiveCaptivemodidObject *captivemodid,const gchar *file_md5) { g_return_val_if_fail(file_md5!=NULL,NULL); - module_md5_hash_init(); - return g_hash_table_lookup(module_md5_hash,file_md5); + return g_hash_table_lookup(captivemodid->module_md5_hash,file_md5); } -gint captive_captivemodid_module_type_best_priority_lookup(const xmlChar *module_type) +gint captive_captivemodid_module_type_best_priority_lookup(CaptiveCaptivemodidObject *captivemodid,const xmlChar *module_type) { gpointer r_gpointer; gboolean errbool; g_return_val_if_fail(module_type!=NULL,G_MININT); - module_type_best_priority_hash_init(); - errbool=g_hash_table_lookup_extended(module_type_best_priority_hash, + errbool=g_hash_table_lookup_extended(captivemodid->module_type_best_priority_hash, module_type, /* lookup_key */ NULL, /* orig_key */ &r_gpointer); /* value */ @@ -180,17 +211,17 @@ gboolean errbool; } /* Returns: TRUE if all modules were found. */ -gboolean captive_captivemodid_module_type_best_priority_found(const xmlChar *module_type) +gboolean captive_captivemodid_module_type_best_priority_found + (CaptiveCaptivemodidObject *captivemodid,const xmlChar *module_type) { gboolean errbool; g_return_val_if_fail(module_type!=NULL,FALSE); - module_type_best_priority_hash_init(); - errbool=g_hash_table_remove(module_type_best_priority_hash,module_type); + errbool=g_hash_table_remove(captivemodid->module_type_best_priority_hash,module_type); g_assert(errbool==TRUE); - return !g_hash_table_size(module_type_best_priority_hash); + return !g_hash_table_size(captivemodid->module_type_best_priority_hash); } static xmlChar *captive_captivemodid_load_module_xml_get_attr @@ -229,7 +260,8 @@ char *ends; return r; } -static void captive_captivemodid_load_module_xml(const gchar *captive_captivemodid_pathname,xmlTextReader *xml_reader) +static void captive_captivemodid_load_module_xml + (CaptiveCaptivemodidObject *captivemodid,const gchar *captive_captivemodid_pathname,xmlTextReader *xml_reader) { struct captive_captivemodid_module *module; xmlChar *cabinet_used_string; @@ -263,14 +295,11 @@ xmlChar *cabinet_used_string; if (G_MININT>=(module->priority=captive_captivemodid_load_module_xml_get_attr_l(captive_captivemodid_pathname,xml_reader,"priority", G_MININT+1,G_MAXINT-1))) goto fail_free_module; - captive_captivemodid_load_module(module); + captive_captivemodid_load_module(captivemodid,module); return; fail_free_module: - xmlFree((xmlChar *)module->type); - xmlFree((xmlChar *)module->md5); - xmlFree((xmlChar *)module->id); - g_free(module); + captive_captivemodid_module_free(module); } static void captive_captivemodid_load_foreach @@ -285,12 +314,19 @@ static void captive_captivemodid_load_foreach void (*captive_captivemodid_module_best_priority_notify)(const gchar *module_type); -gboolean captive_captivemodid_load(const gchar *captive_captivemodid_pathname) +CaptiveCaptivemodidObject *captive_captivemodid_load(const gchar *captive_captivemodid_pathname) { +CaptiveCaptivemodidObject *captivemodid; xmlTextReader *xml_reader; if (!(xml_reader=xmlNewTextReaderFilename(captive_captivemodid_pathname))) return FALSE; + + captivemodid=g_object_new( + CAPTIVE_CAPTIVEMODID_TYPE_OBJECT, /* object_type */ + NULL); /* first_property_name; FIXME: support properties */ + captivemodid->pathname_loaded=g_strdup(captive_captivemodid_pathname); + while (1==xmlTextReaderRead(xml_reader)) { switch (xmlTextReaderNodeType(xml_reader)) { @@ -313,7 +349,7 @@ const xmlChar *xml_name; /**/ if (!xmlStrcmp(xml_name,BAD_CAST "modid")) { /* root tag */ } else if (!xmlStrcmp(xml_name,BAD_CAST "module")) - captive_captivemodid_load_module_xml(captive_captivemodid_pathname,xml_reader); + captive_captivemodid_load_module_xml(captivemodid,captive_captivemodid_pathname,xml_reader); else g_warning(_("%s: Unknown ELEMENT node: %s"),captive_captivemodid_pathname,xml_name); xmlFree((xmlChar *)xml_name); } break; @@ -324,8 +360,59 @@ const xmlChar *xml_name; xmlFreeTextReader(xml_reader); if (captive_captivemodid_module_best_priority_notify) { - g_hash_table_foreach(module_type_best_priority_hash, - (GHFunc)captive_captivemodid_load_foreach,NULL); + g_hash_table_foreach(captivemodid->module_type_best_priority_hash, + (GHFunc)captive_captivemodid_load_foreach, + captivemodid); /* user_data */ } - return TRUE; + + return captivemodid; +} + +CaptiveCaptivemodidObject *captive_captivemodid_load_default(gboolean fatal) +{ +CaptiveCaptivemodidObject *captivemodid=NULL; +const gchar *pathname_default=G_STRINGIFY(SYSCONFDIR) "/w32-mod-id.captivemodid.xml"; +const gchar *msg; + + if ((captivemodid=captive_captivemodid_load(pathname_default))) + return captivemodid; + if ((captivemodid=captive_captivemodid_load("./w32-mod-id.captivemodid.xml"))) + return captivemodid; + msg=_("Unable to load modid database: %s"); + if (fatal) + g_error(msg,pathname_default); + g_warning(msg,pathname_default); + return NULL; +} + +const gchar *captive_captivemodid_get_pathname_loaded(CaptiveCaptivemodidObject *captivemodid) +{ + return captivemodid->pathname_loaded; +} + +gchar *captive_calc_md5(gconstpointer base,size_t length) +{ +unsigned char md5_bin[1+128/8]; /* 128 bits==16 bytes; '1+' for leading stub to prevent shorter output of BN_bn2hex() */ +BIGNUM *bignum; +char *hex; +gchar *r,*gs; + + /* already done above */ + /* Calculate MD5 sum and convert it to hex string: */ + MD5(base,length,md5_bin+1); + md5_bin[0]=0xFF; /* stub to prevent shorter output of BN_bn2hex() */ + bignum=BN_bin2bn(md5_bin,1+128/8,NULL); + hex=BN_bn2hex(bignum); + g_assert(strlen(hex)==2*(1+128/8)); + r=g_strdup(hex+2); + OPENSSL_free(hex); + BN_free(bignum); + + g_assert(strlen(r)==32); + for (gs=r;*gs;gs++) { + g_assert(isxdigit(*gs)); + *gs=tolower(*gs); + g_assert(isxdigit(*gs)); + } + return r; }