static void pdf_set_metainfo(const gchar* filename, GData* metainfo) { gchar tempfile[] = "/tmp/metainfo-XXXXXX"; int fd = mkstemp(tempfile); if (fd < 0) return; // error FILE* f = fdopen(fd, "w"); g_datalist_foreach(&metainfo, print_metainfo, f); fclose(f); gchar* cmdline; { gchar* qf = g_shell_quote(filename); gchar* cmd = g_strdup_printf("set-meta %s; save", tempfile); gchar* qc = g_shell_quote(cmd); g_free(cmd); // "pdftk %s update_info %s output %s", filename, tempfile, new cmdline = g_strdup_printf("djvused %s -e %s", qf, qc); g_free(qf); g_free(qc); } system(cmdline); /* os.unlink(filename) os.rename(new, filename) */ }
static gboolean ibus_serializable_real_serialize (IBusSerializable *object, IBusMessageIter *iter) { IBusSerializablePrivate *priv; IBusMessageIter array_iter; gboolean retval; priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "{sv}", &array_iter); g_return_val_if_fail (retval, FALSE); g_datalist_foreach (&priv->attachments, (GDataForeachFunc) _serialize_cb, &array_iter); retval = ibus_message_iter_close_container (iter, &array_iter); g_return_val_if_fail (retval, FALSE); return TRUE; }
/* Funcion loadAllReceivers * Precondiciones: * Postcondiciones: * Entrada: Cola con los complementos cargados en memoria, cola de mensajes. * Salida: Cola de hilos creados, mensaje de error * Proceso: Inicia los hilos necesarios para cada uno de los complementos cargados. * */ gpointer loadAllReceivers (gpointer data) { ExtThreadData* etData; ForeachData* fData; GData** dPlugins; gint i; etData = data; dPlugins = etData->dPlugins; fData = g_new0(ForeachData, 1); fData->tData = etData->tData; fData->pThreads = g_ptr_array_new(); fData->counter = 0; /* Crea los hilos para las funciones de envío */ g_datalist_foreach(dPlugins, loadReceiver, (gpointer)fData); g_debug("%s - Up & running", MODULENAME); /* Waits for every thread previously created */ if (fData->counter > 0) { for (i = 0; i < fData->counter; i++) { g_thread_join((GThread*)g_ptr_array_index(fData->pThreads, i)); } } else { g_critical("%s - %s", MODULENAME, NOTENOUGHTHREADS); } return (NULL); }
/** * e_uri_copy: * @uri: The #EUri to copy. * * Makes a copy of @uri. * * Returns: The newly-allocated copy of @uri. **/ EUri * e_uri_copy (EUri *uri) { EUri *uri_copy; g_return_val_if_fail (uri != NULL, NULL); uri_copy = g_new0 (EUri, 1); uri_copy->protocol = g_strdup (uri->protocol); uri_copy->user = g_strdup (uri->user); uri_copy->authmech = g_strdup (uri->authmech); uri_copy->passwd = g_strdup (uri->passwd); uri_copy->host = g_strdup (uri->host); uri_copy->port = uri->port; uri_copy->path = g_strdup (uri->path); uri_copy->query = g_strdup (uri->query); uri_copy->fragment = g_strdup (uri->fragment); /* copy uri->params */ g_datalist_foreach (&uri->params, (GDataForeachFunc) copy_param_cb, &uri_copy->params); return uri_copy; }
/** * soup_form_encode_datalist: * @form_data_set: a datalist containing name/value pairs * * Encodes @form_data_set into a value of type * "application/x-www-form-urlencoded", as defined in the HTML 4.01 * spec. Unlike soup_form_encode_hash(), this preserves the ordering * of the form elements, which may be required in some situations. * * Return value: the encoded form **/ char * soup_form_encode_datalist (GData **form_data_set) { GString *str = g_string_new (NULL); g_datalist_foreach (form_data_set, datalist_encode_foreach, str); return g_string_free (str, FALSE); }
static void record_logout_for_all_remaining_sessions (void) { g_datalist_foreach (&humanity_by_session_id, (GDataForeachFunc) record_stop_for_login, NULL /* user_data */); g_datalist_clear (&humanity_by_session_id); }
/** * camel_url_to_string: * @url: a #CamelURL * @flags: additional translation options * * Flatten a #CamelURL into a string. * * Returns: a string representing @url, which the caller must free **/ gchar * camel_url_to_string (CamelURL *url, CamelURLFlags flags) { GString *str; gchar *return_result; g_return_val_if_fail (url != NULL, NULL); /* IF YOU CHANGE ANYTHING IN THIS FUNCTION, RUN * tests/misc/url AFTERWARD. */ #ifdef G_OS_WIN32 if (url->protocol && !strcmp (url->protocol, "file")) return g_filename_to_uri (url->path, url->host, NULL); #endif /* G_OS_WIN32 */ str = g_string_sized_new (20); if (url->protocol) g_string_append_printf (str, "%s:", url->protocol); if (url->host) { g_string_append (str, "//"); if (url->user) { append_url_encoded (str, url->user, ":;@/"); if (url->authmech && *url->authmech && !(flags & CAMEL_URL_HIDE_AUTH)) { g_string_append (str, ";auth="); append_url_encoded (str, url->authmech, ":@/"); } g_string_append_c (str, '@'); } append_url_encoded (str, url->host, ":/"); if (url->port) g_string_append_printf (str, ":%d", url->port); if (!url->path && (url->params || url->query || url->fragment)) g_string_append_c (str, '/'); } if (url->path) append_url_encoded (str, url->path, ";?"); if (url->params && !(flags & CAMEL_URL_HIDE_PARAMS)) g_datalist_foreach (&url->params, output_param, str); if (url->query) { g_string_append_c (str, '?'); append_url_encoded (str, url->query, NULL); } if (url->fragment) { g_string_append_c (str, '#'); append_url_encoded (str, url->fragment, NULL); } return_result = str->str; g_string_free (str, FALSE); return return_result; }
static void debug_print_qdata (GimpObject *object) { g_print ("\nData attached to '%s':\n\n", gimp_object_get_name (object)); g_datalist_foreach (&G_OBJECT (object)->qdata, debug_print_qdata_foreach, NULL); g_print ("\n"); }
static gchar *gfire_sq_gamespy2_details(gfire_game_server *p_server) { GString *str = g_string_new(NULL); gfire_sq_gamespy2_data *data = (gfire_sq_gamespy2_data*)p_server->data->proto_data; // General server infos g_string_append(str, _("<b><font size=\"5\">General Server Details:</font></b><br>")); // Server Name gchar *escaped = gfire_escape_html(p_server->data->name); g_string_append_printf(str, _("<b>Server Name:</b> %s<br>"), escaped); g_free(escaped); // Players g_string_append_printf(str, _("<b>Players:</b> %u/%u<br>"), p_server->data->players, p_server->data->max_players); // Map escaped = gfire_escape_html(p_server->data->map); g_string_append_printf(str, _("<b>Map:</b> %s<br>"), escaped); g_free(escaped); // Password secured g_string_append_printf(str, _("<b>Password secured:</b> %s<br>"), (g_strcmp0("True", g_datalist_get_data(&data->info, "password")) == 0) || (g_strcmp0("1", g_datalist_get_data(&data->info, "password")) == 0) ? _("Yes") : _("No")); // Game Type g_string_append_printf(str, _("<b>Game Type:</b> %s<br>"), g_datalist_get_data(&data->info, "gametype") ? (gchar*)g_datalist_get_data(&data->info, "gametype") : _("N/A")); // Version g_string_append_printf(str, _("<b>Version:</b> %s"), g_datalist_get_data(&data->info, "gamever") ? (gchar*)g_datalist_get_data(&data->info, "gamever") : _("N/A")); // Players g_string_append(str, _("<br><br><b><font size=\"5\">Players:</font></b><br><font face=\"monospace\"><b>Name Score Ping</b><br>")); GSList *cur = data->players; while(cur) { gfire_sq_gamespy2_player *player = (gfire_sq_gamespy2_player*)cur->data; gchar *unescaped = gfire_sq_gamespy2_fixed_len_string(player->name, 16); gchar *name = gfire_escape_html(unescaped); g_free(unescaped); g_string_append_printf(str, "%s %-10d %d<br>", name, player->score, player->ping); g_free(name); cur = g_slist_next(cur); } // Other server rules g_string_append(str, _("<br></font><b><font size=\"5\">All Server Info:</font></b><br>")); g_datalist_foreach(&data->info, gfire_sq_gamespy2_details_vars, str); return g_string_free(str, FALSE); }
// recommend you count number of attributes in advance, to allocate the // propper amount of **. each char *name should be allocated 7 and the char // *val 20 ???? int S57_getAttributes(_S57_geo *geoData, char **name, char **val) { struct _qwerty tmp; tmp.currentIdx = 0; tmp.name = name; tmp.value = val; g_datalist_foreach(&geoData->attribs, _getAttValues, &tmp); // strcpy(name[tmp.currentIdx], "x"); // strcpy(val[tmp.currentIdx], "y"); return tmp.currentIdx; }
static gboolean ibus_serializable_real_copy (IBusSerializable *dest, const IBusSerializable *src) { IBusSerializablePrivate *src_priv; IBusSerializablePrivate *dest_priv; src_priv = IBUS_SERIALIZABLE_GET_PRIVATE (src); dest_priv = IBUS_SERIALIZABLE_GET_PRIVATE (dest); g_datalist_foreach (&src_priv->attachments, (GDataForeachFunc) _copy_cb, &dest_priv->attachments); return TRUE; }
int S57_dumpData(_S57_geo *geoData, int dumpCoords) // debug // if dumpCoords is TRUE dump all coordinates else dump extent { return_if_null(geoData); PRINTF("S57ID : %i\n", geoData->id); PRINTF("NAME : %s\n", geoData->name->str); g_datalist_foreach(&geoData->attribs, _printAtt, NULL); { // print coordinate guint npt = 0; geocoord *ppt; S57_getGeoData(geoData, 0, &npt, &ppt); switch (geoData->obj_t) { case _META_T: PRINTF("_META_T (%i)\n", npt); break; case POINT_T: PRINTF("POINT_T (%i)\n", npt); break; case LINES_T: PRINTF("LINES_T (%i)\n", npt); break; case AREAS_T: PRINTF("AREAS_T (%i)\n", npt); break; default: PRINTF("WARNING: invalid object type; %i\n", geoData->obj_t); } if (TRUE == dumpCoords) { guint npt = 0; geocoord *ppt = NULL; if (FALSE==S57_getGeoData(geoData, 0, &npt, &ppt)) return FALSE; for (guint i=0; i<npt; ++i) { PRINTF("\t\t(%f, %f, %f)\n", ppt[0], ppt[1], ppt[2]); ppt += 3; } } else { // dump extent PRINTF("EXTENT: %f, %f -- %f, %f\n", geoData->rect.y1, geoData->rect.x1, geoData->rect.y2, geoData->rect.x2); } } return TRUE; }
cchar *S57_getAtt(_S57_geo *geoData) { return_if_null(geoData); PRINTF("S57ID : %i\n", geoData->id); PRINTF("NAME : %s\n", geoData->name->str); g_string_set_size(_attList, 0); g_string_printf(_attList, "%i", geoData->id); g_datalist_foreach(&geoData->attribs, _getAtt, _attList); return _attList->str; }
/** * camel_url_copy: * @in: a #CamelURL to copy * * Copy a #CamelURL. * * Returns: a duplicate copy of @in **/ CamelURL * camel_url_copy (CamelURL *in) { CamelURL *out; g_return_val_if_fail (in != NULL, NULL); out = g_malloc0 (sizeof (*out)); out->protocol = g_strdup (in->protocol); out->user = g_strdup (in->user); out->authmech = g_strdup (in->authmech); out->host = g_strdup (in->host); out->port = in->port; out->path = g_strdup (in->path); out->params = NULL; if (in->params) g_datalist_foreach (&((CamelURL *) in)->params, copy_param, &out->params); out->query = g_strdup (in->query); out->fragment = g_strdup (in->fragment); return out; }
/** * g_dataset_foreach: * @dataset_location: (not nullable): the location identifying the dataset. * @func: (scope call): the function to call for each data element. * @user_data: (closure): user data to pass to the function. * * Calls the given function for each data element which is associated * with the given location. Note that this function is NOT thread-safe. * So unless @dataset_location can be protected from any modifications * during invocation of this function, it should not be called. * * @func can make changes to the dataset, but the iteration will not * reflect changes made during the g_dataset_foreach() call, other * than skipping over elements that are removed. **/ void g_dataset_foreach (gconstpointer dataset_location, GDataForeachFunc func, gpointer user_data) { GDataset *dataset; g_return_if_fail (dataset_location != NULL); g_return_if_fail (func != NULL); G_LOCK (g_dataset_global); if (g_dataset_location_ht) { dataset = g_dataset_lookup (dataset_location); G_UNLOCK (g_dataset_global); if (dataset) g_datalist_foreach (&dataset->datalist, func, user_data); } else { G_UNLOCK (g_dataset_global); } }
static gchar *gfire_sq_savage_details(gfire_game_server *p_server) { GString *str = g_string_new(NULL); gchar *escaped; gchar *html; gfire_sq_savage_data *data = (gfire_sq_savage_data*)p_server->data->proto_data; // General server infos g_string_append(str, _("<b><font size=\"5\">General Server Details:</font></b><br>")); // Server Name if(g_datalist_get_data(&data->info, "name")) { escaped = gfire_escape_html(g_datalist_get_data(&data->info, "name")); html = gfire_sq_savage_color_codes_to_html(escaped); g_free(escaped); g_string_append_printf(str, _("<b>Server Name:</b> %s<br>"), html); g_free(html); } else g_string_append_printf(str, _("<b>Server Name:</b> %s<br>"), _("N/A")); // Players g_string_append_printf(str, _("<b>Players:</b> %u/%u<br>"), p_server->data->players, p_server->data->max_players); // Map escaped = gfire_escape_html(p_server->data->map); g_string_append_printf(str, _("<b>Map:</b> %s<br>"), escaped); g_free(escaped); // Password secured g_string_append_printf(str, _("<b>Password secured:</b> %s<br>"), (g_strcmp0("1", g_datalist_get_data(&data->info, "pass")) == 0) ? _("Yes") : _("No")); // Game Type if(g_datalist_get_data(&data->info, "gametype")) { escaped = gfire_escape_html(g_datalist_get_data(&data->info, "gametype")); html = gfire_sq_savage_color_codes_to_html(escaped); g_free(escaped); g_string_append_printf(str, _("<b>Game Type:</b> %s<br>"), html); g_free(html); } else g_string_append_printf(str, _("<b>Game Type:</b> %s<br>"), _("N/A")); // Version if(g_datalist_get_data(&data->info, "ver")) { escaped = gfire_escape_html(g_datalist_get_data(&data->info, "ver")); html = gfire_sq_savage_color_codes_to_html(escaped); g_free(escaped); g_string_append_printf(str, _("<b>Version:</b> %s"), html); g_free(html); } else g_string_append_printf(str, _("<b>Version:</b> %s"), _("N/A")); // Players g_string_append(str, _("<br><br><b><font size=\"5\">Players:</font></b><br>")); gchar **cur = data->players; while(cur && *cur) { escaped = gfire_escape_html(*cur); html = gfire_sq_savage_color_codes_to_html(escaped); g_free(escaped); g_string_append_printf(str, "%s<br>", html); g_free(html); cur++; } // Other server rules g_string_append(str, _("<br></font><b><font size=\"5\">All Server Info:</font></b><br>")); g_datalist_foreach(&data->info, gfire_sq_savage_details_vars, str); return g_string_free(str, FALSE); }
static int qp_load_pgn_fp (qipu_t *qipu, FILE *fp) { char line[0x500], pan[10][9], *b, *e, *m; const char *fen; int incommet, isred; #ifdef _DEBUG char move_str[0x100]; #endif while (fgets (line, sizeof line, fp) != NULL) { b = strchr (line, '['); if (b == NULL) { break; } do { ++ b; } while (isspace (*b)); if (*b == '\0') { acc_warn ("parser line: '%s' error.\n", line); break; } m = strchr (b, ' '); if (m == NULL) { m = strchr (b, '\t'); } if (m == NULL) { acc_warn ("parser line: '%s' error.\n", line); break; } *m = '\0'; /* token end */ do { ++ m; } while (isspace (*m)); e = strchr (m, ']'); if (e == NULL) { acc_warn ("parser line: '%s' error.\n", line); break; } do { *e = '\0'; -- e; } while (isspace (*e)); if (*m == '"' || *m == '\'') { ++ m; } if (*e == '"' || *e == '\'') { *e = '\0'; } qipu_set_info (qipu, b, m); } #ifdef _DEBUG g_datalist_foreach (&qipu->tv_list, (GDataForeachFunc) qp_output_tv_debug, NULL); #endif fen = qipu_get_info (qipu, "FEN"); if (fen == NULL) { fen = qipu_get_info (qipu, "fen"); } if (fen) { fen_from_string (qipu->fen, fen); memcpy (pan, qipu->fen->pan, 10 * 9 * sizeof (char)); } else { memcpy (pan, default_pan, 10 * 9 * sizeof (char)); } incommet = 0; isred = 1; do { //acc_debug ("get line: [%s]\n", line); b = line; if (incommet) { b = strchr (b, '}'); if (b == NULL) { continue; } else { incommet = 0; ++ b; } } while (isspace (*b)) { ++ b; } if (*b == '{') { b = strchr (b, '}'); if (b == NULL) { incommet = 1; continue; } else { ++ b; } } while (isspace (*b)) { ++ b; } if (*b == '\0') { continue; } while (*b != '\0') { struct xq_move move[1]; int offset; /* strip blank or numbers and . */ while (isspace (*b)) { ++ b; } while (desc_get_number (b, &offset) >= 0) { b += offset; } if (*b == '.') { ++ b; } while (isspace (*b)) { ++ b; } if (*b == '\0') { break; } move->isred = isred; isred = isred ? 0: 1; #ifdef _DEBUG acc_debug ("\n\nbegin move\n"); output_pan (pan); #endif offset = desc_to_move (pan, b, move); if (offset <= 0) { break; } b += offset; #ifdef _DEBUG move_to_desc (pan, move, move_str, sizeof move_str); acc_debug ("desc: %s\n", move_str); #endif pan[move->toy][move->tox] = pan[move->fromy][move->fromx]; pan[move->fromy][move->fromx] = 0; qipu_append_move (qipu, move); #ifdef _DEBUG output_pan (pan); acc_debug ("after move\n\n"); #endif } //acc_debug ("get not commet: [%s]\n", b); } while (fgets (line, sizeof line, fp) != NULL); return 0; }
static gchar *gfire_sq_ase_details(gfire_game_server *p_server) { GString *str = g_string_new(NULL); gfire_sq_ase_data *data = (gfire_sq_ase_data*)p_server->data->proto_data; // General server infos g_string_append(str, _("<b><font size=\"5\">General Server Details:</font></b><br>")); // Server Name gchar *escaped = gfire_escape_html(data->server_name); gchar *name = gfire_sq_ase_color_codes_to_html(escaped); g_free(escaped); g_string_append_printf(str, _("<b>Server Name:</b> %s<br>"), name); g_free(name); // Players g_string_append_printf(str, _("<b>Players:</b> %u/%u<br>"), p_server->data->players, p_server->data->max_players); // Map escaped = gfire_escape_html(data->map); g_string_append_printf(str, _("<b>Map:</b> %s<br>"), escaped); g_free(escaped); // Password secured g_string_append_printf(str, _("<b>Password secured:</b> %s<br>"), data->password ? _("Yes") : _("No")); // Game Type g_string_append_printf(str, _("<b>Game Type:</b> %s<br>"), data->game_type); // Version g_string_append_printf(str, _("<b>Version:</b> %s"), data->version); // Players g_string_append(str, _("<br><br><b><font size=\"5\">Players:</font></b><br><font face=\"monospace\"><b>Name Score Ping</b><br>")); GSList *cur = data->players; while(cur) { gfire_sq_ase_player *player = (gfire_sq_ase_player*)cur->data; gchar *stripped = gfire_sq_ase_strip_color_codes(player->name ? player->name : _("N/A")); gchar *unescaped = gfire_sq_ase_fixed_len_string(stripped, 16); g_free(stripped); gchar *name = gfire_escape_html(unescaped); g_free(unescaped); unescaped = gfire_sq_ase_fixed_len_string(player->score ? player->score : _("N/A"), 10); gchar *score = gfire_escape_html(unescaped); g_free(unescaped); gchar *ping = gfire_escape_html(player->ping ? player->ping : _("N/A")); g_string_append_printf(str, "%s %s %s<br>", name, score, ping); g_free(ping); g_free(score); g_free(name); cur = g_slist_next(cur); } // Other server rules g_string_append(str, _("<br></font><b><font size=\"5\">All Server Rules:</font></b><br>")); g_datalist_foreach(&data->rules, gfire_sq_ase_details_vars, str); return g_string_free(str, FALSE); }
int S57_getNumAtt(S57_geo *geoData) { int cnt = 0; g_datalist_foreach(&geoData->attribs, _countItems, &cnt); return cnt; }
void nube_sources_update() { g_datalist_foreach(&used_sources, (GDataForeachFunc) _update_source, NULL); }
/** * camel_url_new_with_base: * @base: a base URL * @url_string: the URL * * Parses @url_string relative to @base. * * Returns: a parsed #CamelURL **/ CamelURL * camel_url_new_with_base (CamelURL *base, const gchar *url_string) { CamelURL *url; const gchar *end, *hash, *colon, *semi, *at, *slash, *question; const gchar *p; #ifdef G_OS_WIN32 const gchar *start = url_string; #endif g_return_val_if_fail (url_string != NULL, NULL); url = g_new0 (CamelURL, 1); /* See RFC1808 for details. IF YOU CHANGE ANYTHING IN THIS * FUNCTION, RUN tests/misc/url AFTERWARDS. */ /* Find fragment. RFC 1808 2.4.1 */ end = hash = strchr (url_string, '#'); if (hash) { if (hash[1]) { url->fragment = g_strdup (hash + 1); camel_url_decode (url->fragment); } } else end = url_string + strlen (url_string); /* Find protocol: initial [a-z+.-]* substring until ":" */ p = url_string; while (p < end && (isalnum ((guchar) * p) || *p == '.' || *p == '+' || *p == '-')) p++; if (p > url_string && *p == ':') { url->protocol = g_strndup (url_string, p - url_string); camel_strdown (url->protocol); url_string = p + 1; } if (!*url_string && !base) return url; #ifdef G_OS_WIN32 if (url->protocol && !strcmp (url->protocol, "file")) { url->path = g_filename_from_uri (start, &url->host, NULL); return url; } #endif /* Check for authority */ if (strncmp (url_string, "//", 2) == 0) { url_string += 2; slash = url_string + strcspn (url_string, "/#"); at = strchr (url_string, '@'); if (at && at < slash) { colon = strchr (url_string, ':'); if (colon && colon < at) { /* XXX We used to extract and store the * password here, now we just eat it. */ } else { colon = at; } semi = strchr (url_string, ';'); if (semi && semi < colon && !g_ascii_strncasecmp (semi, ";auth=", 6)) { url->authmech = g_strndup ( semi + 6, colon - semi - 6); camel_url_decode (url->authmech); } else { url->authmech = NULL; semi = colon; } url->user = g_strndup (url_string, semi - url_string); camel_url_decode (url->user); url_string = at + 1; } else url->user = url->authmech = NULL; /* Find host and port. */ colon = strchr (url_string, ':'); if (colon && colon < slash) { url->host = g_strndup (url_string, colon - url_string); url->port = strtoul (colon + 1, NULL, 10); } else { url->host = g_strndup (url_string, slash - url_string); camel_url_decode (url->host); url->port = 0; } url_string = slash; } /* Find query */ question = memchr (url_string, '?', end - url_string); if (question) { if (question[1]) { url->query = g_strndup ( question + 1, end - (question + 1)); camel_url_decode (url->query); } end = question; } /* Find parameters */ semi = memchr (url_string, ';', end - url_string); if (semi) { if (semi[1]) { const gchar *cur, *p, *eq; gchar *name, *value; for (cur = semi + 1; cur < end; cur = p + 1) { p = memchr (cur, ';', end - cur); if (!p) p = end; eq = memchr (cur, '=', p - cur); if (eq) { name = g_strndup (cur, eq - cur); value = g_strndup (eq + 1, p - (eq + 1)); camel_url_decode (value); } else { name = g_strndup (cur, p - cur); value = g_strdup (""); } camel_url_decode (name); g_datalist_set_data_full ( &url->params, name, value, g_free); g_free (name); } } end = semi; } if (end != url_string) { url->path = g_strndup (url_string, end - url_string); camel_url_decode (url->path); } /* Apply base URL. Again, this is spelled out in RFC 1808. */ if (base && !url->protocol && url->host) url->protocol = g_strdup (base->protocol); else if (base && !url->protocol) { if (!url->user && !url->authmech && !url->host && !url->port && !url->path && !url->params && !url->query && !url->fragment) url->fragment = g_strdup (base->fragment); url->protocol = g_strdup (base->protocol); url->user = g_strdup (base->user); url->authmech = g_strdup (base->authmech); url->host = g_strdup (base->host); url->port = base->port; if (!url->path) { url->path = g_strdup (base->path); if (!url->params) { g_datalist_foreach (&base->params, copy_param, &url->params); if (!url->query) url->query = g_strdup (base->query); } } else if (*url->path != '/') { gchar *newpath, *last, *p, *q; /* the base->path is NULL if given Content-Base url was without last slash, * i.e. like "http://example.com" (this expected only "http://example.com/") */ last = base->path ? strrchr (base->path, '/') : NULL; if (last) { newpath = g_strdup_printf ( "%.*s/%s", (gint)(last - base->path), base->path, url->path); } else newpath = g_strdup_printf ("/%s", url->path); /* Remove "./" where "." is a complete segment. */ for (p = newpath + 1; *p; ) { if (*(p - 1) == '/' && *p == '.' && *(p + 1) == '/') memmove (p, p + 2, strlen (p + 2) + 1); else p++; } /* Remove "." at end. */ if (p > newpath + 2 && *(p - 1) == '.' && *(p - 2) == '/') *(p - 1) = '\0'; /* Remove "<segment>/../" where <segment> != ".." */ for (p = newpath + 1; *p; ) { if (!strncmp (p, "../", 3)) { p += 3; continue; } q = strchr (p + 1, '/'); if (!q) break; if (strncmp (q, "/../", 4) != 0) { p = q + 1; continue; } memmove (p, q + 4, strlen (q + 4) + 1); p = newpath + 1; } /* Remove "<segment>/.." at end */ q = strrchr (newpath, '/'); if (q && !strcmp (q, "/..")) { p = q - 1; while (p > newpath && *p != '/') p--; if (strncmp (p, "/../", 4) != 0) *(p + 1) = 0; } g_free (url->path); url->path = newpath; } } return url; }