Beispiel #1
0
void
load_configuration ()
{
    l_debug ("Loading configuration for Profile:%s",profile);

    if (config != NULL)
        g_hash_table_remove_all (config);
    config = g_hash_table_new (g_str_hash, g_str_equal);
    MYSQL_ROW row;
    MYSQL_RES *result;
    int res =
      do_query (FALSE, lyricDb, "SELECT config_key,config_value FROM config WHERE profile='%s'", profile);
    if (res != 0) {
        return;
    }
    result = mysql_store_result (lyricDb);
    gboolean conf_found = FALSE;
    while ((row = mysql_fetch_row (result))) {
        conf_found = TRUE;
        g_hash_table_insert (config, g_strdup (row[0]), g_strdup (row[1]));
        l_debug ("Config \"%s\" set to \"%s\"", row[0], row[1]);
    }
    if (!conf_found) {
        l_debug ("No configuration found - load lyricue to setup");
        exit (1);
    }
    load_font_defaults ();
    mysql_free_result (result);
}
Beispiel #2
0
MYSQL *
db_connect (const char *dbname, const char *dberror)
{
    MYSQL *tempDb = mysql_init (NULL);
    if (tempDb == NULL) {
        l_debug ("Error %u: %s", mysql_errno (tempDb),
                   mysql_error (tempDb));
        g_warning ("Error %u: %s", mysql_errno (tempDb),
                   mysql_error (tempDb));
        exit (1);
    }
    my_bool reconnect = 1;
    mysql_options (tempDb, MYSQL_OPT_RECONNECT, &reconnect);

    if (mysql_real_connect
        (tempDb, dbhostname, "lyric", "", dbname, 0, NULL, 0) == NULL) {
        l_debug ("Error %u: %s", mysql_errno (tempDb),
                   mysql_error (tempDb));
        g_warning ("Error %u: %s", mysql_errno (tempDb),
                   mysql_error (tempDb));
        return NULL;
    }
    // Re-run for mysql versions < 5.0.19
    mysql_options (tempDb, MYSQL_OPT_RECONNECT, &reconnect);
    mysql_set_character_set (tempDb, "utf8");

    return tempDb;
}
Beispiel #3
0
// copies keys from the source that don't exist on the target
LClosure *l_closure_backfill(LClosure *source, LClosure *target, LNode *node) {
    l_debug(L_DEBUG_STACK) printf("+++ backfilling closure\n");
    target->node = node;
    l_clone_vars_if_missing(source->vars, target->vars);
    l_clone_vars_if_missing(source->locals, target->locals);
    return target;
}
Beispiel #4
0
 static int SetArgMem(lua_State *L) {
     cl_kernel krnl = *traits::CheckObject(L, 1);
     cl_uint index = static_cast<cl_uint>(luaL_checknumber(L, 2));
     luacl_buffer_object *buffer = traits_buffer::CheckObject(L, 3);
     l_debug(L, "kernel:SetArg index %d, buffer %p, mem %p", index, buffer, buffer->mem);
     cl_int err = clSetKernelArg(krnl, index - 1, sizeof(cl_mem), &(buffer->mem));
     CheckCLError(L, err, "Failed setting kernel arg as mem object: %s.");
     return 0;
 }
Beispiel #5
0
// creates and initializes an empty closure
LClosure *l_closure_new(LNode *node) {
    l_debug(L_DEBUG_STACK) printf("+++ creating new closure\n");
    LClosure *closure = GC_MALLOC(sizeof(LClosure));
    closure->vars = create_hashmap();
    closure->locals = create_hashmap();
    closure->parent = NULL;
    closure->cloneable = true;
    closure->node = node;
    return closure;
}
Beispiel #6
0
void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
    assert(g == group || group == NULL);
    group = g;

    /* Called whenever the entry group state changes */

    switch (state) {
        case AVAHI_ENTRY_GROUP_ESTABLISHED :
            /* The entry group has been established successfully */
            l_debug("Service '%s' successfully established.", name);
            break;

        case AVAHI_ENTRY_GROUP_COLLISION : {
            char *n;

            /* A service name collision with a remote service
             * happened. Let's pick a new name */
            n = avahi_alternative_service_name(name);
            avahi_free(name);
            name = n;

            l_debug("Service name collision, renaming service to '%s'", name);

            /* And recreate the services */
            create_services(avahi_entry_group_get_client(g));
            break;
        }

        case AVAHI_ENTRY_GROUP_FAILURE :

            l_debug("Entry group failure: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));

            /* Some kind of failure happened while we were registering our services */
            avahi_simple_poll_quit(simple_poll);
            break;

        case AVAHI_ENTRY_GROUP_UNCOMMITED:
        case AVAHI_ENTRY_GROUP_REGISTERING:
            ;
    }
}
Beispiel #7
0
// We use this simple function for translating strings from the browser into
// cstrings. These strings can be untrusted, so verify them carefully.
bool netscape_string_convert(NPString *string, char **output)
{
    // Sanity check the string length.
    if (string->UTF8Length > kNetscapeStringMax) {
        l_debug("refusing to convert very long string, length %u",
                string->UTF8Length);
        return false;
    }

    // Does it contain nuls or other indicators of encoding issues?
    if (strnlen(string->UTF8Characters, string->UTF8Length) != string->UTF8Length) {
        l_debug("refusing to convert weird encoding, %u != %u, %s",
                strnlen(string->UTF8Characters, string->UTF8Length),
                string->UTF8Length,
                string->UTF8Characters);
        return false;
    }

    // Okay, it seems sane. Copy the output.
    return !! (*output = strndup(string->UTF8Characters, string->UTF8Length));
}
Beispiel #8
0
int
do_query (gboolean silent, MYSQL * dbconnection, const char * format, ...)
{
    if (dbconnection != NULL) {
        GString *query = g_string_new (NULL);
        va_list argp;
        va_start (argp, format);
        g_string_vprintf (query, format, argp);
        va_end (argp);
    
        if (!silent) l_debug ("SQL: %s", query->str);
        if (mysql_query (dbconnection, query->str)) {
            l_debug (_("SQL Error %u: %s"), mysql_errno (dbconnection),
                    mysql_error (dbconnection));
        }
        g_string_free (query, TRUE);
        return mysql_errno (dbconnection);
    } else {
        l_debug("Database not connected");
    }
    return -1;
}
Beispiel #9
0
// creates a new closure from the given parent closure
LClosure *l_closure_clone(LClosure *parent, LNode *node) {
    l_debug(L_DEBUG_STACK) printf("+++ cloning closure\n");
    if(!parent->cloneable) return parent;
    LClosure *closure = GC_MALLOC(sizeof(LClosure));
    closure->vars = create_hashmap();
    closure->locals = create_hashmap();
    closure->parent = parent;
    closure->cloneable = true;
    closure->node = node;
    // copy vars from function closure
    l_clone_vars(parent->vars, closure->vars);
    l_clone_vars(parent->locals, closure->locals);
    return closure;
}
Beispiel #10
0
int publish_avahi(int port_passed, char *type_in_passed) {
    int error;
    AvahiGLibPoll *glib_poll;
    port = port_passed;
    type_in = strndup(type_in_passed,32);

    avahi_set_allocator (avahi_glib_allocator ());

    /* Create the GLIB Adaptor */
    glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);

    name = avahi_strdup("Lyricue Display");

    /* Allocate a new client */
    client = avahi_client_new(avahi_glib_poll_get(glib_poll), 0, client_callback, NULL, &error);

    /* Check if creating the client object succeeded */
    if (!client) {
        l_debug("Failed to create client: %s", avahi_strerror(error));
        unpublish_avahi();
    }

    
    /* Create the service browser */
    if (miniviews==NULL) {
        miniviews = g_hash_table_new(g_str_hash, g_str_equal);
    }
    if (sb == NULL) {
        if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, "_lyricue._tcp", NULL, 0, browse_callback, client))) {
            l_debug("Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
        }
    }


    return 0;
}
Beispiel #11
0
// Used to percent encode messages so we can ignore sanitisation.
static bool encode_javascript_string(const char *message, char **output)
{
    // Sanity check parameters.
    if (!message || strlen(message) > kMessageLengthMax)
        return false;

    // Allow for triple expansion.
    if (!(*output = malloc(strlen(message) * 3 + 1))) {
        l_debug("memory allocation failure constructing message");
        return false;
    }

    // Safely encode string using percent-encodiung.
    for (**output = 0; *message; message++) {
        sprintf(*output + strlen(*output), "%%%02hx", *message);
    }

    return true;
}
Beispiel #12
0
// Apple don't use a simple callback to NP_GetMIMEDescription, as on Linux, but
// we still need to implement it as we can dynamically open other plugins.
//
// XXX: For the initial release, I'm not going to support external MIME types. I
//      will add it on request.
char * platform_getmimedescription(struct plugin *plugin)
{
    CFDictionaryRef     cf_pluginplist   = NULL;
    CFDictionaryRef     cf_mimetypes     = NULL;
    CFBundleRef         cf_plugin        = plugin->handle;
    char               *mime_description = strdup("");

    // If we don't have a valid handle, we return an empty MIME description.
    // This is jsut for convenience so that I don't have to special case
    // invalid plugins on shutdown.
    if (plugin->handle == NULL) {
        goto finished;
    }

    // We should already have a CFBundleRef in plugin->handle.
    cf_pluginplist = CFBundleGetInfoDictionary(cf_plugin);

    // Find the WebPluginMIMETypes key.
    if (CFDictionaryGetValueIfPresent(cf_pluginplist,
                                      CFSTR("WebPluginMIMETypes"),
                                      (const void **) &cf_mimetypes) == false) {
        // The plugin is invalid, malformed, or using external MIME Types. This
        // is not currently supported, so return an empty string.
        goto finished;
    }

    if (CFGetTypeID(cf_mimetypes) != CFDictionaryGetTypeID()) {
        goto finished;
    }

    l_debug("found %u keys in WebPluginMIMETypes dictionary from plugin %s",
            CFDictionaryGetCount(cf_mimetypes),
            plugin->section);

    // Enumerate each key in the dictionary, adding them to the description.
    CFDictionaryApplyFunction(cf_mimetypes,
                              mimetype_dictionary_applier,
                              &mime_description);

finished:
    // Return the final string.
    return mime_description;
}
Beispiel #13
0
void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
    assert(c);

    /* Called whenever the client or server state changes */

    switch (state) {
        case AVAHI_CLIENT_S_RUNNING:

            /* The server has startup successfully and registered its host
             * name on the network, so it's time to create our services */
            create_services(c);
            break;

        case AVAHI_CLIENT_FAILURE:

            l_debug("Client failure: %s", avahi_strerror(avahi_client_errno(c)));
            avahi_simple_poll_quit(simple_poll);

            break;

        case AVAHI_CLIENT_S_COLLISION:

            /* Let's drop our registered services. When the server is back
             * in AVAHI_SERVER_RUNNING state we will register them
             * again with the new host name. */

        case AVAHI_CLIENT_S_REGISTERING:

            /* The server records are now being established. This
             * might be caused by a host name change. We need to wait
             * for our own records to register until the host name is
             * properly esatblished. */

            if (group)
                avahi_entry_group_reset(group);

            break;

        case AVAHI_CLIENT_CONNECTING:
            ;
    }
}
Beispiel #14
0
void create_services(AvahiClient *c) {
    char *n;
    gchar *type_txt, *profile_txt, *data_txt; 
    int ret;
    assert(c);

    /* If this is the first time we're called, let's create a new
     * entry group if necessary */

    if (!group)
        if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
            l_debug("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(c)));
            goto fail;
        }

    /* If the group is empty (either because it was just created, or
     * because it was reset previously, add our entries.  */

    if (avahi_entry_group_is_empty(group)) {
        l_debug("Adding service '%s' type '%s'", name, type_in);

        /* Set type of service */
        profile_txt = g_strdup_printf("profile=%s", profile);
        type_txt = g_strdup_printf("type=%s", type_in);
        if (extra_data == NULL) {
            extra_data = g_strdup("");
        }
        data_txt = g_strdup_printf("data=%s", extra_data);

        /* Add the service for Lyricue Display */
        if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, "_lyricue._tcp", NULL, NULL, port, type_txt, profile_txt, data_txt, NULL)) < 0) {

            if (ret == AVAHI_ERR_COLLISION)
                goto collision;

            l_debug("Failed to add _lyricue._tcp service: %s", avahi_strerror(ret));
            goto fail;
        }
        g_free(profile_txt);
        g_free(type_txt);
        g_free(data_txt);

        /* Tell the server to register the service */
        if ((ret = avahi_entry_group_commit(group)) < 0) {
            l_debug("Failed to commit entry group: %s", avahi_strerror(ret));
            goto fail;
        }
    }

    return;

collision:

    /* A service name collision with a local service happened. Let's
     * pick a new name */
    n = avahi_alternative_service_name(name);
    avahi_free(name);
    name = n;

    l_debug("Service name collision, renaming service to '%s'", name);

    avahi_entry_group_reset(group);

    create_services(c);
    return;

fail:
    avahi_simple_poll_quit(simple_poll);
}
Beispiel #15
0
void resolve_callback(
    AvahiServiceResolver *r,
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char *name,
    const char *type,
    const char *domain,
    const char *host_name,
    const AvahiAddress *address,
    uint16_t port,
    AvahiStringList *txt,
    AvahiLookupResultFlags flags,
    AVAHI_GCC_UNUSED void* userdata) {

    assert(r);

    /* Called whenever a service has been resolved successfully or timed out */

    switch (event) {
        case AVAHI_RESOLVER_FAILURE:
            l_debug("(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
            break;

        case AVAHI_RESOLVER_FOUND: {
            char a[AVAHI_ADDRESS_STR_MAX];

            avahi_address_snprint(a, sizeof(a), address);
            char *value;
            char *type = NULL;
            size_t *size=NULL;
            AvahiStringList *type_txt = avahi_string_list_find(txt,"type");
            if (type_txt != NULL){
                avahi_string_list_get_pair(type_txt,&type, &value, size);
                l_debug("Type = %s",value);
                if ((g_strcmp0(value,"miniview") == 0) || (g_strcmp0(value,"android") == 0)) {
                    char *data="data";
                    char *extra_data;
                    size_t *size2=NULL;
                    AvahiStringList *data_txt = avahi_string_list_find(txt,"data");
                    if (data_txt != NULL) {
                        avahi_string_list_get_pair(data_txt,&data, &extra_data, size2);
                        gchar *myhost = g_strdup_printf("%s:%u",hostname,server_port);
                        if (g_strcmp0(extra_data, myhost)==0) {
                            gchar *host = g_strdup_printf("%s:%u",a, port);
                            l_debug("Found miniview on %s", host);
                            if (!g_hash_table_contains(miniviews,host)) {
                                g_hash_table_insert(miniviews, g_strdup(name), host);
                            }
                        }
                        avahi_free(data);
                        avahi_free(extra_data);
                        g_free(myhost);
                    }
                }
                avahi_free(value);
                avahi_free(type);
            }
        }
    }

    avahi_service_resolver_free(r);
}
Beispiel #16
0
bool netscape_plugin_geturl(NPP instance, char **url)
{
    void          *window;
    NPIdentifier  *locationid;
    NPIdentifier  *hrefid;
    NPVariant      location;
    NPVariant      href;

    // We need often need to query the url hosting the current instance to
    // apply our policy logic. This routine handles that.
    //
    // We do this by querying window.location.href, while this may seem
    // fragile, it's actually the officially supported method of retrieving the
    // URL. Being able to fool it would break most popular plugins, so we can
    // rely on browser vendors maintaining it.
    if (registry.netscape_funcs->getvalue(instance,
                                          NPNVWindowNPObject,
                                          &window) != NPERR_NO_ERROR) {
        l_debug("failed to fetch window object for instance %p", instance);
        return false;
    }

    // Create required identifiers to query the objects.
    //
    // Why not use location.hostname?
    //
    // > location.__defineGetter__("hostname", function () { return "arbitrary"; })
    // > undefined
    // > location.hostname
    // > "arbitrary"
    //
    // In fact the browser guarantees nothing except window.location.href.
    locationid = registry.netscape_funcs->getstringidentifier("location");
    hrefid = registry.netscape_funcs->getstringidentifier("href");

    // Get the Location object.
    if (!registry.netscape_funcs->getproperty(instance,
                                              window,
                                              locationid,
                                              &location)
            || !NPVARIANT_IS_OBJECT(location)) {
        l_debug("failed to fetch location object for instance %p", instance);
        return false;
    }

    // Get the URL from the Location object via href.
    if (!registry.netscape_funcs->getproperty(instance,
                                              location.value.objectValue,
                                              hrefid,
                                              &href)
            || !NPVARIANT_IS_STRING(href)) {
        l_warning("failed to fetch href string for instance %p", instance);
        return false;
    }

    // No longer need location object.
    registry.netscape_funcs->releasevariantvalue(&location);

    // Finally, Convert the NPString returned into a C string.
    if (!netscape_string_convert(&NPVARIANT_TO_STRING(href), url)) {
        l_warning("failed to convert NPString to c string for %p", instance);
        return false;
    }

    // Clear the NPString.
    registry.netscape_funcs->releasevariantvalue(&href);

    return true;
}
Beispiel #17
0
// We may want to display a message to the user, but don't want to have to
// create our own windows. We can ask the browser to display it instead, but
// have to be careful about what we send.
bool netscape_display_message(NPP instance, const char *message)
{
    void     *element;
    char     *encoded;
    NPError   result;
    NPString  script;
    NPVariant output;

    // Verify the parameters are sane,
    if (!message || !instance) {
        l_debug("invalid instance or message received, cannot display");
        return false;
    }

    // No need to actually display the empty message
    if (!strlen(message)) {
        return true;
    }

    // Retrieve the plugin object.
    if (registry.netscape_funcs->getvalue(instance,
                                          NPNVPluginElementNPObject,
                                          &element) != NPERR_NO_ERROR) {
        l_debug("unable to retrieve element object to display message");
        return false;
    }

    // We cannot display a message this way in Firefox due to a bug.
    if (strstr(registry.netscape_funcs->uagent(instance), "Firefox")) {
        l_warning("FIXME: unable to display messages in FireFox due to a bug");
        return false;
    }

    // Percent encode the required string.
    if (!encode_javascript_string(message, &encoded)) {
        l_debug("unable to construct javascript safe string, failed");
        return false;
    }

    // To produce the final message, we need to allow for the code to alert and
    // unescape the message as well.
    script.UTF8Characters = alloca(strlen(encoded)
                                 + strlen(kJSDisplayEncodedMessageFormat));

    // Produce the NPString, which doesn't want the terminating nul. Luckily,
    // that's what sprintf returns.
    script.UTF8Length = sprintf((char *) script.UTF8Characters,
                                kJSDisplayEncodedMessageFormat,
                                encoded);

    // This should evaluate the script NPString in the context of the plugin
    // object.
    result = registry.netscape_funcs->evaluate(instance,
                                               element,
                                               &script,
                                               &output);


    // Print debugging message if that failed.
    if (result != NPERR_NO_ERROR) {
        l_debug("netscape returned error displaying message %s", encoded);
    }

    // Clean up.
    registry.netscape_funcs->releasevariantvalue(&output);
    free(encoded);

    return result == NPERR_NO_ERROR;
}
Beispiel #18
0
// Find the matching plugin structure for the section name `section`. If no
// such section exists, a new one is allocated and returned. If the section
// name matches the special name "Global", it is added to the appropriate list.
//
// Returns true on success, false on failure.
static bool find_plugin_section(struct registry *registry,
                                const char *section,
                                struct plugin **plugin)
{
    struct plugin *current;

    // Check if this is the special "Global" section used to specify default
    // parameters and other special values.
    if (strcmp(section, "Global") == 0) {

        // If this is the first value from the Global section, we need to
        // create it.
        if (registry->global == NULL) {

            // Allocate a new structure.
            if ((*plugin = calloc(1, sizeof(**plugin))) == NULL) {
                l_error("memory allocation failure");
                return false;
            }

            // Install as the global plugin.
            registry->global            = *plugin;
            registry->global->section   = strdup(section);
        }

        // Return pointer to parent.
        *plugin = registry->global;

        // Success.
        return !! registry->global->section;
    } else {
        // This is not the Global section, a regular plugin section.
        current = registry->plugins;

        for (current = registry->plugins; current; current = current->next) {
            // Search to see if we already recognise this section.
            if (strcmp(current->section, section) == 0) {
                // Match found.
                *plugin = current;

                return true;
            }
        }
    }

    // This is the first time we've seen this section, we have to set it up.
    l_debug("new plugin section %s discovered", section);

    // Allocate a new structure.
    if ((*plugin = calloc(1, sizeof(**plugin))) == NULL) {
        l_error("memory allocation failure");
        return false;
    }

    // Check if we have any other plugins registered.
    if (registry->plugins != NULL) {

        // Find the tail of the plugin registry.
        for (current = registry->plugins; current->next; current = current->next)
            ;

        // Add to the list.
        current->next = *plugin;
        current = current->next;
        current->section = strdup(section);
    } else {
        // This is the first plugin structure we've seen, create the list head.
        registry->plugins = *plugin;
        registry->plugins->section = strdup(section);
        current = registry->plugins;
    }

    // Success.
    return !! current->section;
}
Beispiel #19
0
LValue *l_eval_call_node(LNode *node, LValue *func, LClosure *closure) {

  if(func == NULL) func = l_eval_var_node(node, closure);

  char *name = (node != NULL) ? node->val : "";

  LValue *value, *args_val;
  LNode *expr;
  int i;

  // create a running scope to hold arguments
  // and a reference to self (for recursion)
  // TODO this may not be necessary (can't we just do `cl=func->core.func.closure`?)
  LClosure *cl = l_closure_clone(func->core.func.closure, node);

tail_loop:

  l_debug(L_DEBUG_CALL) {
    if(node) printf(">>> entering %s on line %d in %s\n", name, node->line_no, node->source_file);
    else printf(">>> entering %s\n", name);
  }

  if(strcmp(name, "") != 0)
    l_closure_set(cl, name, func, true);

  args_val = l_eval_call_args(node, func, closure, cl);

  if(func->core.func.ptr != NULL) {
    // native C code
    if(!setjmp(cl->jmp)) {
      value = func->core.func.ptr(args_val, cl);
    } else {
      // function called longjmp to initiate a tail call
      l_debug(L_DEBUG_CALL) printf("^^^ reached end of %s (longjmp tail call)\n", name);
      node = NULL;
      func = l_closure_get(cl, "--tail-call--");
      closure = cl;
      l_closure_backfill(func->core.func.closure, cl, node);
      name = "";
      goto tail_loop;
    }
  } else {
    // Lydia code
    int exprc = func->core.func.exprc;
    if(exprc > 0) {
      // eval all but the last expression
      for(i=0; i<exprc-1; i++) {
        expr = func->core.func.exprs[i];
        value = l_eval_node(expr, cl);
      }
      expr = func->core.func.exprs[exprc-1];
      if(expr->type == L_CALL_TYPE) { // tail call
        l_debug(L_DEBUG_CALL) printf("^^^ reached end of %s (tail call)\n", name);
        node = expr;
        func = l_eval_var_node(node, cl);
        closure = cl;
        l_closure_backfill(func->core.func.closure, cl, node);
        name = node->val;
        goto tail_loop;
      } else {
        value = l_eval_node(expr, cl);
      }
    } else {
      value = l_value_new(L_NIL_TYPE, cl);
    }
  }

  l_closure_free(cl);

  l_debug(L_DEBUG_CALL) printf("<<< returning from %s\n", name);

  return value;
}
Beispiel #20
0
// Helper function to construct strings for CFDictionaryApplyFunction in
// platform_getmimedescription()
//  key     CFString containing a MIME type.
//  value   CFDictionary containing descriptions and extensions.
//  context char * where we want our NP_GetMIMETypeDescription compatible output.
static void mimetype_dictionary_applier(const void *key,
                                        const void *value,
                                        void *context)
{
    CFDictionaryRef cf_mimetype_dict    = value;
    CFStringRef     cf_mimetype         = key;
    CFIndex         cf_length;
    CFArrayRef      cf_extensions;
    CFStringRef     cf_description;
    CFBooleanRef    cf_enabled;
    char           *mimetype            = strdupa("");
    char           *description         = strdupa("");
    char           *extensions          = strdup("");
    char          **result              = context;

    // Here is an example of the output we want:
    //
    // "application/example:ext1,ext2:Example MIME Type"
    //

    // Verify that we received a CFDictionary object.
    if (CFGetTypeID(cf_mimetype_dict) != CFDictionaryGetTypeID()) {
        goto finished;
    }

    // Verify that the key is a CFString.
    if (CFGetTypeID(cf_mimetype) != CFStringGetTypeID()) {
        goto finished;
    }

    // Find the length of the MIME Type, and allocate stack space for it.
    cf_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cf_mimetype),
                                                  kCFStringEncodingUTF8);
    mimetype = alloca(cf_length + 1);

    // Extract the string.
    if (CFStringGetCString(cf_mimetype,
                           mimetype,
                           cf_length + 1,
                           kCFStringEncodingUTF8) != true) {
        goto finished;
    }

    // First we need to check if this type is disabled via WebPluginTypeEnabled.
    if (CFDictionaryGetValueIfPresent(cf_mimetype_dict,
                                      CFSTR("WebPluginTypeEnabled"),
                                      (const void **) &cf_enabled)) {
        // Verify that is a CFBoolean
        if (CFGetTypeID(cf_enabled) != CFBooleanGetTypeID()) {
            goto finished;
        }

        // Test value.
        if (CFBooleanGetValue(cf_enabled) == false) {
            goto finished;
        }
    }


    // Verify we have an empty string.
    if (!extensions) {
        goto finished;
    }

    // Now we need to lookup the extensions requested by the plugin.
    if (CFDictionaryGetValueIfPresent(cf_mimetype_dict,
                                      CFSTR("WebPluginExtensions"),
                                      (const void **) &cf_extensions)) {
        if (CFGetTypeID(cf_extensions) != CFArrayGetTypeID()) {
            goto finished;
        }

        l_debug("discovered %u extensions defined for mimetype %s",
                CFArrayGetCount(cf_extensions),
                mimetype);

        // Apply a function to every extension listed to concatenate them.
        CFArrayApplyFunction(cf_extensions,
                             CFRangeMake(0, CFArrayGetCount(cf_extensions)),
                             extension_array_applier,
                             &extensions);
    }

    // Now we need the description which is a CFString
    if (CFDictionaryGetValueIfPresent(cf_mimetype_dict,
                                      CFSTR("WebPluginTypeDescription"),
                                      (const void **) &cf_description)) {
        if (CFGetTypeID(cf_description) != CFStringGetTypeID()) {
            goto finished;
        }

        // Find the length of the MIME Type, and allocate stack space for it.
        cf_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cf_description),
                                                      kCFStringEncodingUTF8);
        description = alloca(cf_length + 1);

        // Extract the string.
        if (CFStringGetCString(cf_description,
                               description,
                               cf_length + 1,
                               kCFStringEncodingUTF8) != true) {
            goto finished;
        }
    }

    // So now we need to assemble the final string.
    *result = realloc(*result,
                      (*result ? strlen(*result) : 0)
                        + strlen(mimetype) + 1
                        + strlen(description) + 1
                        + strlen(extensions) + 1
                        + 1
                        + 1);

    // Verify that worked.
    if (!*result) {
        goto finished;
    }

    // Create the final string.
    sprintf(*result, "%s%s%s:%s:%s",
            *result,
            strlen(*result) ? ";" : "",
            mimetype,
            extensions,
            description);

    l_debug("successfully processed mimetype %s", mimetype);

finished:
    free(extensions);
    return;
}
Beispiel #21
0
void l_closure_free(LClosure *closure) {
    l_debug(L_DEBUG_STACK) printf("--- freeing closure\n");
    if(closure->parent == NULL) return;
}