#include <ctype.h>
-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 */
}
/* 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
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;
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
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)) {
/**/ 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;
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;
}