static void cookiejar_changed(SoupCookieJar *self, SoupCookie *old_cookie, SoupCookie *new_cookie) { FLOCK(COOKIEJAR(self)->lock, F_WRLCK); SoupDate *expire; if (new_cookie) { /* session-expire-time handling */ if (vb.config.cookie_expire_time == 0) { soup_cookie_set_expires(new_cookie, NULL); } else if (vb.config.cookie_expire_time > 0 && new_cookie->expires) { expire = soup_date_new_from_now(vb.config.cookie_expire_time); if (soup_date_to_time_t(expire) < soup_date_to_time_t(new_cookie->expires)) { soup_cookie_set_expires(new_cookie, expire); } soup_date_free(expire); } /* session-cookie handling */ if (!new_cookie->expires && vb.config.cookie_timeout) { expire = soup_date_new_from_now(vb.config.cookie_timeout); soup_cookie_set_expires(new_cookie, expire); soup_date_free(expire); } } SOUP_COOKIE_JAR_CLASS(cookiejar_parent_class)->changed(self, old_cookie, new_cookie); FLOCK(COOKIEJAR(self)->lock, F_UNLCK); }
/* soup_cookie_equal wasn't good enough */ inline static gboolean soup_cookie_truly_equal(SoupCookie *c1, SoupCookie *c2) { return (!g_strcmp0(c1->name, c2->name) && !g_strcmp0(c1->value, c2->value) && !g_strcmp0(c1->path, c2->path) && (c1->secure == c2->secure) && (c1->http_only == c2->http_only) && (c1->expires && c2->expires && (soup_date_to_time_t(c1->expires) == soup_date_to_time_t(c2->expires)))); }
static void katze_http_cookies_jar_changed_cb (SoupCookieJar* jar, SoupCookie* old_cookie, SoupCookie* new_cookie, KatzeHttpCookies* http_cookies) { GObject* settings; guint accept_cookies; if (old_cookie) soup_cookie_set_max_age (old_cookie, 0); if (new_cookie) { settings = g_object_get_data (G_OBJECT (jar), "midori-settings"); accept_cookies = katze_object_get_enum (settings, "accept-cookies"); if (accept_cookies == 2 /* MIDORI_ACCEPT_COOKIES_NONE */) { soup_cookie_set_max_age (new_cookie, 0); } else if (accept_cookies == 1 /* MIDORI_ACCEPT_COOKIES_SESSION */ && new_cookie->expires) { soup_cookie_set_max_age (new_cookie, -1); } else if (new_cookie->expires) { gint age = katze_object_get_int (settings, "maximum-cookie-age"); if (age > 0) { SoupDate* max_date = soup_date_new_from_now ( age * SOUP_COOKIE_MAX_AGE_ONE_DAY); if (soup_date_to_time_t (new_cookie->expires) > soup_date_to_time_t (max_date)) soup_cookie_set_expires (new_cookie, max_date); } else { /* An age of 0 to SoupCookie means already-expired A user choosing 0 days probably expects 1 hour. */ soup_cookie_set_max_age (new_cookie, SOUP_COOKIE_MAX_AGE_ONE_HOUR); } } } if (g_getenv ("MIDORI_COOKIES_DEBUG") != NULL) http_cookies->counter++; if (!http_cookies->timeout && (old_cookie || new_cookie->expires)) http_cookies->timeout = g_timeout_add_seconds (5, (GSourceFunc)katze_http_cookies_update_jar, http_cookies); }
static gchar *cm_get_cookie_description_text(SoupCookie *cookie) { gchar *expires; gchar *text; g_return_val_if_fail(cookie != NULL, NULL); if (cookie->expires != NULL) { time_t expiration_time = soup_date_to_time_t(cookie->expires); GDateTime* date = g_date_time_new_from_unix_local(expiration_time); expires = g_date_time_format(date, "%c"); g_date_time_unref(date); } else expires = g_strdup(_("At the end of the session")); text = g_markup_printf_escaped( _("<b>Host</b>: %s\n<b>Name</b>: %s\n<b>Value</b>: %s\n<b>Path</b>: %s\n" "<b>Secure</b>: %s\n<b>Expires</b>: %s"), cookie->domain, cookie->name, cookie->value, cookie->path, /* i18n: is this cookie secure (SSL)? yes/ no */ cookie->secure ? _("Yes") : _("No"), expires); g_free(expires); return text; }
Eina_List* ewk_cookies_get_all(void) { Eina_List* result = 0; GSList* list; GSList* p; SoupCookieJar* cookieJar = WebCore::soupCookieJar(); list = soup_cookie_jar_all_cookies(cookieJar); for (p = list; p; p = p->next) { SoupCookie* cookie = static_cast<SoupCookie*>(p->data); Ewk_Cookie* ewkCookie = new Ewk_Cookie; ewkCookie->name = eina_stringshare_add(cookie->name); ewkCookie->value = eina_stringshare_add(cookie->value); ewkCookie->domain = eina_stringshare_add(cookie->domain); ewkCookie->path = eina_stringshare_add(cookie->path); ewkCookie->expires = soup_date_to_time_t(cookie->expires); ewkCookie->secure = static_cast<Eina_Bool>(cookie->secure); ewkCookie->http_only = static_cast<Eina_Bool>(cookie->http_only); result = eina_list_append(result, ewkCookie); } soup_cookies_free(list); return result; }
/** * Returns a list of cookies in the cookie jar. * * @return an @c Eina_List with all the cookies in the cookie jar. */ Eina_List* ewk_cookies_get_all(void) { Eina_List* el = 0; #if USE(SOUP) GSList* l; GSList* p; SoupCookieJar* cookieJar = WebCore::defaultCookieJar(); l = soup_cookie_jar_all_cookies(cookieJar); for (p = l; p; p = p->next) { SoupCookie* cookie = static_cast<SoupCookie*>(p->data); Ewk_Cookie* c = static_cast<Ewk_Cookie*>(malloc(sizeof(*c))); c->name = strdup(cookie->name); c->value = strdup(cookie->value); c->domain = strdup(cookie->domain); c->path = strdup(cookie->path); c->expires = soup_date_to_time_t(cookie->expires); c->secure = static_cast<Eina_Bool>(cookie->secure); c->http_only = static_cast<Eina_Bool>(cookie->http_only); el = eina_list_append(el, c); } soup_cookies_free(l); #endif return el; }
static gint luaH_cookie_push(lua_State *L, SoupCookie *c) { lua_createtable(L, 0, 7); #define PUSH_PROP(prop, type) \ lua_pushliteral(L, #prop); \ lua_push##type(L, c->prop); \ lua_rawset(L, -3); PUSH_PROP(name, string) PUSH_PROP(value, string) PUSH_PROP(domain, string) PUSH_PROP(path, string) PUSH_PROP(secure, boolean) PUSH_PROP(http_only, boolean) #undef PUSH_PROP /* push expires */ lua_pushliteral(L, "expires"); if (c->expires) lua_pushnumber(L, soup_date_to_time_t(c->expires)); else lua_pushnumber(L, -1); lua_rawset(L, -3); return 1; }
static void sanity_check_date (RestProxyCall *call) { GHashTable *headers; SoupDate *call_date; const char *s; time_t call_time, diff; headers = rest_proxy_call_get_response_headers (call); s = g_hash_table_lookup (headers, "Date"); if (s) { call_date = soup_date_new_from_string (s); if (call_date) { call_time = soup_date_to_time_t (call_date); diff = labs (time (NULL) - call_time); /* More than five minutes difference between local time and the response time? */ if (diff > (60 * 5)) { g_warning ("%ld seconds difference between HTTP time and system time!", diff); } } soup_date_free (call_date); } g_hash_table_unref (headers); }
/* local_db_needs_update function returns TRUE on success and FALSE on failure. * It sets the parameter needs_update to TRUE if the local database needs * to be updated. */ static gboolean local_db_needs_update (SoupSession *session, const char *db_uri, GFile *db_local, gboolean *needs_update, GError **error) { GFileInfo *db_local_info; SoupMessage *msg; SoupDate *date; const gchar *db_time_str; guint64 db_time; guint64 db_local_time; guint status_code; if (g_file_query_exists (db_local, NULL) == FALSE) { *needs_update = TRUE; return TRUE; } msg = soup_message_new ("HEAD", db_uri); status_code = soup_session_send_message (session, msg); if (status_code != SOUP_STATUS_OK) { g_set_error_literal (error, SOUP_HTTP_ERROR, status_code, msg->reason_phrase); return FALSE; } db_time_str = soup_message_headers_get_one (msg->response_headers, "Last-Modified"); date = soup_date_new_from_string (db_time_str); db_time = (guint64) soup_date_to_time_t (date); soup_date_free (date); g_object_unref (msg); db_local_info = g_file_query_info (db_local, "time::modified", G_FILE_QUERY_INFO_NONE, NULL, error); if (!db_local_info) return FALSE; db_local_time = g_file_info_get_attribute_uint64 (db_local_info, "time::modified"); if (db_time <= db_local_time) *needs_update = FALSE; else *needs_update = TRUE; g_object_unref (db_local_info); return TRUE; }
/** * soup_date_is_past: * @date: a #SoupDate * * Determines if @date is in the past. * * Return value: %TRUE if @date is in the past * * Since: 2.24 **/ gboolean soup_date_is_past (SoupDate *date) { g_return_val_if_fail (date != NULL, TRUE); /* optimization */ if (date->year < 2008) return TRUE; return soup_date_to_time_t (date) < time (NULL); }
static gint64 utils_http_full_date_to_timestamp(const char* string) { gint64 ret; SoupDate* tmp; tmp = soup_date_new_from_string(string); ret = soup_date_to_time_t(tmp); soup_date_free(tmp); return ret; }
gint64 utils_http_full_date_to_timestamp(const char* string) { gint64 ret = G_MAXINT64; g_autoptr(SoupDate) date = NULL; date = soup_date_new_from_string(string); RETURN_VAL_IF_FAIL(date != NULL, ret); ret = soup_date_to_time_t(date); return ret; }
static void write_cookie (FILE *out, SoupCookie *cookie) { fseek (out, 0, SEEK_END); fprintf (out, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n", cookie->http_only ? "#HttpOnly_" : "", cookie->domain, *cookie->domain == '.' ? "TRUE" : "FALSE", cookie->path, cookie->secure ? "TRUE" : "FALSE", (gulong)soup_date_to_time_t (cookie->expires), cookie->name, cookie->value); }
/* Cookie jar saving to Mozilla format Copyright (C) 2008 Xan Lopez <*****@*****.**> Copyright (C) 2008 Dan Winship <*****@*****.**> Copied from libSoup 2.24, coding style preserved */ static gboolean write_cookie (FILE *out, SoupCookie *cookie) { if (fprintf (out, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n", cookie->http_only ? "#HttpOnly_" : "", cookie->domain, *cookie->domain == '.' ? "TRUE" : "FALSE", cookie->path, cookie->secure ? "TRUE" : "FALSE", (gulong)soup_date_to_time_t (cookie->expires), cookie->name, cookie->value) < 0) return FALSE; return TRUE; }
time_t twitter_http_date_to_time_t (const gchar *date) { SoupDate *soup_date; time_t retval; g_return_val_if_fail (date != NULL, (time_t) -1); soup_date = soup_date_new_from_string (date); if (!soup_date) return (time_t) -1; retval = soup_date_to_time_t (soup_date); soup_date_free (soup_date); return retval; }
static void network_process_callback (SoupSession *session, SoupMessage *msg, gpointer user_data) { updateJobPtr job = (updateJobPtr)user_data; SoupDate *last_modified; const gchar *tmp = NULL; job->result->source = soup_uri_to_string (soup_message_get_uri(msg), FALSE); if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { job->result->returncode = msg->status_code; job->result->httpstatus = 0; } else { job->result->httpstatus = msg->status_code; job->result->returncode = 0; } debug1 (DEBUG_NET, "download status code: %d", msg->status_code); debug1 (DEBUG_NET, "source after download: >>>%s<<<", job->result->source); job->result->data = g_memdup (msg->response_body->data, msg->response_body->length+1); job->result->size = (size_t)msg->response_body->length; debug1 (DEBUG_NET, "%d bytes downloaded", job->result->size); job->result->contentType = g_strdup (soup_message_headers_get_content_type (msg->response_headers, NULL)); /* Update last-modified date */ tmp = soup_message_headers_get_one (msg->response_headers, "Last-Modified"); if (tmp) { /* The string may be badly formatted, which will make * soup_date_new_from_string() return NULL */ last_modified = soup_date_new_from_string (tmp); if (last_modified) { job->result->updateState->lastModified = soup_date_to_time_t (last_modified); soup_date_free (last_modified); } } /* Update ETag value */ tmp = soup_message_headers_get_one (msg->response_headers, "ETag"); if (tmp) { job->result->updateState->etag = g_strdup(tmp); } update_process_finished_job (job); }
static void changed (SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) { SoupCookieJarSqlitePrivate *priv = SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar); sqlite3 *db; char *query; if (sqlite3_open (priv->filename, &db)) { sqlite3_close (db); g_warning ("Can't open %s", priv->filename); return; } if (old_cookie) { query = sqlite3_mprintf (QUERY_DELETE, old_cookie->name, old_cookie->domain); exec_query_with_try_create_table (db, query, NULL, NULL); sqlite3_free (query); } if (new_cookie && new_cookie->expires) { gulong expires; expires = (gulong)soup_date_to_time_t (new_cookie->expires); query = sqlite3_mprintf (QUERY_INSERT, new_cookie->name, new_cookie->value, new_cookie->domain, new_cookie->path, expires, new_cookie->secure, new_cookie->http_only); exec_query_with_try_create_table (db, query, NULL, NULL); sqlite3_free (query); } sqlite3_close (db); }
gboolean twitter_date_to_time_val (const gchar *date, GTimeVal *time_) { time_t res; SoupDate *soup_date; g_return_val_if_fail (date != NULL, FALSE); g_return_val_if_fail (time_ != NULL, FALSE); soup_date = soup_date_new_from_string (date); if (soup_date) { res = soup_date_to_time_t (soup_date); soup_date_free (soup_date); time_->tv_sec = res; time_->tv_usec = 0; return TRUE; } #ifdef HAVE_STRPTIME { struct tm tmp; /* OMFG, what are they? insane? */ strptime (date, "%a %b %d %T %z %Y", &tmp); res = mktime (&tmp); if (res != 0) { time_->tv_sec = res; time_->tv_usec = 0; return TRUE; } } #endif /* HAVE_STRPTIME */ return FALSE; }
gint64 feed_get_element_date (FeedParser* fparser) { time_t date; gchar* content; date = 0; content = feed_get_element_string (fparser); if (content) { SoupDate* sdate; sdate = soup_date_new_from_string (content); date = soup_date_to_time_t (sdate); soup_date_free (sdate); g_free (content); } return ((gint64)date); }
bool getRawCookies(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& url, Vector<Cookie>& rawCookies) { rawCookies.clear(); SoupCookieJar* jar = cookieJarForSession(session); if (!jar) return false; GUniquePtr<SoupURI> uri = url.createSoupURI(); GUniquePtr<GSList> cookies(soup_cookie_jar_get_cookie_list(jar, uri.get(), TRUE)); if (!cookies) return false; for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) { SoupCookie* cookie = static_cast<SoupCookie*>(iter->data); rawCookies.append(Cookie(String::fromUTF8(cookie->name), String::fromUTF8(cookie->value), String::fromUTF8(cookie->domain), String::fromUTF8(cookie->path), cookie->expires ? static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000 : 0, cookie->http_only, cookie->secure, !cookie->expires)); soup_cookie_free(cookie); } return true; }
static void changed (SoupCookieJar *jar, SoupCookie *old_cookie, SoupCookie *new_cookie) { SoupCookieJarSqlitePrivate *priv = SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar); char *query; if (priv->db == NULL) { if (open_db (jar)) return; } if (old_cookie) { query = sqlite3_mprintf (QUERY_DELETE, old_cookie->name, old_cookie->domain); exec_query_with_try_create_table (priv->db, query, NULL, NULL); sqlite3_free (query); } if (new_cookie && new_cookie->expires) { gulong expires; expires = (gulong)soup_date_to_time_t (new_cookie->expires); query = sqlite3_mprintf (QUERY_INSERT, new_cookie->name, new_cookie->value, new_cookie->domain, new_cookie->path, expires, new_cookie->secure, new_cookie->http_only); exec_query_with_try_create_table (priv->db, query, NULL, NULL); sqlite3_free (query); } }
bool getRawCookies(NetworkingContext* context, const KURL& /*firstParty*/, const KURL& url, Vector<Cookie>& rawCookies) { rawCookies.clear(); SoupCookieJar* jar = context ? cookieJarForContext(context) : soupCookieJar(); if (!jar) return false; GOwnPtr<GSList> cookies(soup_cookie_jar_all_cookies(jar)); if (!cookies) return false; GOwnPtr<SoupURI> uri(soup_uri_new(url.string().utf8().data())); for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) { GOwnPtr<SoupCookie> cookie(static_cast<SoupCookie*>(iter->data)); if (!soup_cookie_applies_to_uri(cookie.get(), uri.get())) continue; rawCookies.append(Cookie(String::fromUTF8(cookie->name), String::fromUTF8(cookie->value), String::fromUTF8(cookie->domain), String::fromUTF8(cookie->path), static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000, cookie->http_only, cookie->secure, soup_cookie_jar_is_persistent(jar))); } return true; }
static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *context, gpointer data) { const char *last_modified, *etag; const char *header; guint status = SOUP_STATUS_OK; if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); return; } header = soup_message_headers_get_one (msg->request_headers, "Test-Set-Expires"); if (header) { soup_message_headers_append (msg->response_headers, "Expires", header); } header = soup_message_headers_get_one (msg->request_headers, "Test-Set-Cache-Control"); if (header) { soup_message_headers_append (msg->response_headers, "Cache-Control", header); } last_modified = soup_message_headers_get_one (msg->request_headers, "Test-Set-Last-Modified"); if (last_modified) { soup_message_headers_append (msg->response_headers, "Last-Modified", last_modified); } etag = soup_message_headers_get_one (msg->request_headers, "Test-Set-ETag"); if (etag) { soup_message_headers_append (msg->response_headers, "ETag", etag); } header = soup_message_headers_get_one (msg->request_headers, "If-Modified-Since"); if (header && last_modified) { SoupDate *date; time_t lastmod, check; date = soup_date_new_from_string (last_modified); lastmod = soup_date_to_time_t (date); soup_date_free (date); date = soup_date_new_from_string (header); check = soup_date_to_time_t (date); soup_date_free (date); if (lastmod <= check) status = SOUP_STATUS_NOT_MODIFIED; } header = soup_message_headers_get_one (msg->request_headers, "If-None-Match"); if (header && etag) { if (!strcmp (header, etag)) status = SOUP_STATUS_NOT_MODIFIED; } if (status == SOUP_STATUS_OK) { GChecksum *sum; const char *body; sum = g_checksum_new (G_CHECKSUM_SHA256); g_checksum_update (sum, (guchar *)path, strlen (path)); if (last_modified) g_checksum_update (sum, (guchar *)last_modified, strlen (last_modified)); if (etag) g_checksum_update (sum, (guchar *)etag, strlen (etag)); body = g_checksum_get_string (sum); soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, body, strlen (body) + 1); g_checksum_free (sum); } soup_message_set_status (msg, status); }
void soup_cookie_jar_add_cookie(SoupCookieJar *jar, SoupCookie *cookie) { struct wl_entry *w = NULL; SoupCookie *c; FILE *r_cookie_f; char *public_suffix; DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: %p %p %p\n", jar, p_cookiejar, s_cookiejar); if (cookies_enabled == 0) return; /* see if we are up and running */ if (p_cookiejar == NULL) { _soup_cookie_jar_add_cookie(jar, cookie); return; } /* disallow p_cookiejar adds, shouldn't happen */ if (jar == p_cookiejar) return; /* sanity */ if (jar == NULL || cookie == NULL) return; /* check if domain is valid */ public_suffix = tld_get_suffix(cookie->domain[0] == '.' ? cookie->domain + 1 : cookie->domain); if (public_suffix == NULL || (enable_cookie_whitelist && (w = wl_find(cookie->domain, &c_wl)) == NULL)) { blocked_cookies++; DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: reject %s\n", cookie->domain); if (save_rejected_cookies) { if ((r_cookie_f = fopen(rc_fname, "a+")) == NULL) { show_oops(NULL, "can't open reject cookie file"); return; } fseek(r_cookie_f, 0, SEEK_END); fprintf(r_cookie_f, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n", cookie->http_only ? "#HttpOnly_" : "", cookie->domain, *cookie->domain == '.' ? "TRUE" : "FALSE", cookie->path, cookie->secure ? "TRUE" : "FALSE", cookie->expires ? (gulong)soup_date_to_time_t(cookie->expires) : 0, cookie->name, cookie->value); fflush(r_cookie_f); fclose(r_cookie_f); } if (!allow_volatile_cookies) return; } if (cookie->expires == NULL && session_timeout) { soup_cookie_set_expires(cookie, soup_date_new_from_now(session_timeout)); print_cookie("modified add cookie", cookie); } /* see if we are white listed for persistence */ if ((w && w->handy) || (enable_cookie_whitelist == 0)) { /* add to persistent jar */ c = soup_cookie_copy(cookie); print_cookie("soup_cookie_jar_add_cookie p_cookiejar", c); _soup_cookie_jar_add_cookie(p_cookiejar, c); } /* add to session jar */ print_cookie("soup_cookie_jar_add_cookie s_cookiejar", cookie); _soup_cookie_jar_add_cookie(s_cookiejar, cookie); }
/** * twitter_date_to_time_val: * @date: a timestamp coming from Twitter * @time_: return location for a #GTimeVal * * Converts a Twitter date into a #GTimeVal. The timestamp is relative * to UTC. * * Return value: %TRUE if the conversion was successful */ gboolean twitter_date_to_time_val (const gchar *date, GTimeVal *time_) { time_t res; SoupDate *soup_date; g_return_val_if_fail (date != NULL, FALSE); g_return_val_if_fail (time_ != NULL, FALSE); /* XXX - this code is here in case there's a sudden onset of sanity * at Twitter and they switch to using any format supported by libsoup */ soup_date = soup_date_new_from_string (date); if (soup_date) { res = soup_date_to_time_t (soup_date); soup_date_free (soup_date); time_->tv_sec = res; time_->tv_usec = 0; return TRUE; } #ifdef HAVE_STRPTIME { struct tm tmp; /* OMFG, ctime()? really? what are they? insane? I swear, this is * what happens when you let ruby developers write public APIs * * what happened to ISO8601 and web datestamps? you work on the web, * people! */ strptime (date, "%a %b %d %T %z %Y", &tmp); #ifdef HAVE_TIMEGM time_->tv_sec = timegm (&tmp); time_->tv_usec = 0; return TRUE; #else { res = 0; if (tmp.tm_mon < 0 || tmp.tm_mon > 11) { time_->tv_sec = res; time_->tv_usec = 0; return FALSE; } res += (tmp.tm_year - 70) * 365; res += (tmp.tm_year - 68) / 4; res += days_before[tmp.tm_mon] + tmp.tm_mday - 1; if (tmp.tm_year % 4 == 0 && tmp.tm_mon < 2) res -= 1; res = ((((res * 24) + tmp.tm_hour) * 60) + tmp.tm_min) * 60 + tmp.tm_sec; time_->tv_sec = res; time_->tv_usec = 0; return TRUE; } #endif /* HAVE_TIMEGM */ } #endif /* HAVE_STRPTIME */ return FALSE; }
static void resource_available (GSSDPResourceBrowser *resource_browser, SoupMessageHeaders *headers) { GSSDPResourceBrowserPrivate *priv; const char *usn; const char *header; Resource *resource; gboolean was_cached; guint timeout; GList *locations; gboolean destroyLocations; GList *it1, *it2; char *canonical_usn; priv = gssdp_resource_browser_get_instance_private (resource_browser); usn = soup_message_headers_get_one (headers, "USN"); if (!usn) return; /* No USN specified */ /* Build list of locations */ locations = NULL; destroyLocations = TRUE; header = soup_message_headers_get_one (headers, "Location"); if (header) locations = g_list_append (locations, g_strdup (header)); header = soup_message_headers_get_one (headers, "AL"); if (header) { /* Parse AL header. The format is: * <uri1><uri2>... */ const char *start, *end; char *uri; start = header; while ((start = strchr (start, '<'))) { start += 1; if (!start || !*start) break; end = strchr (start, '>'); if (!end || !*end) break; uri = g_strndup (start, end - start); locations = g_list_append (locations, uri); start = end; } } if (!locations) return; /* No location specified */ if (priv->version > 0) { char *version; version = g_strrstr (usn, ":"); canonical_usn = g_strndup (usn, version - usn); } else { canonical_usn = g_strdup (usn); } /* Get from cache, if possible */ resource = g_hash_table_lookup (priv->resources, canonical_usn); /* Put usn into fresh resources, so this resource will not be * removed on cache refreshing. */ if (priv->fresh_resources != NULL) { g_hash_table_add (priv->fresh_resources, g_strdup (canonical_usn)); } /* If location does not match, expect that we missed bye bye packet */ if (resource) { for (it1 = locations, it2 = resource->locations; it1 && it2; it1 = it1->next, it2 = it2->next) { if (strcmp ((const char *) it1->data, (const char *) it2->data) != 0) { resource_unavailable (resource_browser, headers); /* Will be destroyed by resource_unavailable */ resource = NULL; break; } } } if (resource) { /* Remove old timeout */ g_source_destroy (resource->timeout_src); was_cached = TRUE; } else { /* Create new Resource data structure */ resource = g_slice_new (Resource); resource->resource_browser = resource_browser; resource->usn = g_strdup (usn); resource->locations = locations; destroyLocations = FALSE; /* Ownership passed to resource */ g_hash_table_insert (priv->resources, canonical_usn, resource); was_cached = FALSE; /* hash-table takes ownership of this */ canonical_usn = NULL; } g_free (canonical_usn); /* Calculate new timeout */ header = soup_message_headers_get_one (headers, "Cache-Control"); if (header) { GSList *list; int res; res = 0; for (list = soup_header_parse_list (header); list; list = list->next) { res = sscanf (list->data, "max-age = %d", &timeout); if (res == 1) break; } if (res != 1) { g_warning ("Invalid 'Cache-Control' header. Assuming " "default max-age of %d.\n" "Header was:\n%s", SSDP_DEFAULT_MAX_AGE, header); timeout = SSDP_DEFAULT_MAX_AGE; } soup_header_free_list (list); } else { const char *expires; expires = soup_message_headers_get_one (headers, "Expires"); if (expires) { SoupDate *soup_exp_time; time_t exp_time, cur_time; soup_exp_time = soup_date_new_from_string (expires); exp_time = soup_date_to_time_t (soup_exp_time); soup_date_free (soup_exp_time); cur_time = time (NULL); if (exp_time > cur_time) timeout = exp_time - cur_time; else { g_warning ("Invalid 'Expires' header. Assuming " "default max-age of %d.\n" "Header was:\n%s", SSDP_DEFAULT_MAX_AGE, expires); timeout = SSDP_DEFAULT_MAX_AGE; } } else { g_warning ("No 'Cache-Control' nor any 'Expires' " "header was specified. Assuming default " "max-age of %d.", SSDP_DEFAULT_MAX_AGE); timeout = SSDP_DEFAULT_MAX_AGE; } } resource->timeout_src = g_timeout_source_new_seconds (timeout); g_source_set_callback (resource->timeout_src, resource_expire, resource, NULL); g_source_attach (resource->timeout_src, g_main_context_get_thread_default ()); g_source_unref (resource->timeout_src); /* Only continue with signal emission if this resource was not * cached already */ if (!was_cached) { /* Emit signal */ g_signal_emit (resource_browser, signals[RESOURCE_AVAILABLE], 0, usn, locations); } /* Cleanup */ if (destroyLocations) g_list_free_full (locations, g_free); }