NetSurf
html_css_fetcher.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
3  * Copyright 2013 John-Mark Bell <jmb@netsurf-browser.org>
4  *
5  * This file is part of NetSurf.
6  *
7  * NetSurf is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * NetSurf is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * \file
22  * HTML fetcher for CSS objects
23  */
24 
25 #include <assert.h>
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <dom/dom.h>
30 #include <libwapcaplet/libwapcaplet.h>
31 
32 #include "netsurf/inttypes.h"
33 #include "utils/config.h"
34 #include "utils/corestrings.h"
35 #include "utils/log.h"
36 #include "utils/ring.h"
37 #include "utils/nsurl.h"
38 #include "utils/utils.h"
39 #include "content/fetch.h"
40 #include "content/fetchers.h"
41 
42 #include "html/html_internal.h"
43 
44 typedef struct html_css_fetcher_item {
45  uint32_t key;
46  dom_string *data;
48 
51 
52 typedef struct html_css_fetcher_context {
54 
57 
58  bool aborted;
59  bool locked;
60 
63 
64 static uint32_t current_key = 0;
67 
68 static bool html_css_fetcher_initialise(lwc_string *scheme)
69 {
70  NSLOG(netsurf, INFO, "html_css_fetcher_initialise called for %s",
71  lwc_string_data(scheme));
72  return true;
73 }
74 
75 static void html_css_fetcher_finalise(lwc_string *scheme)
76 {
77  NSLOG(netsurf, INFO, "html_css_fetcher_finalise called for %s",
78  lwc_string_data(scheme));
79 }
80 
82 {
83  return true;
84 }
85 
87  bool only_2xx, bool downgrade_tls, const char *post_urlenc,
88  const struct fetch_multipart_data *post_multipart,
89  const char **headers)
90 {
92  lwc_string *path;
93  uint32_t key;
94  html_css_fetcher_item *item, *found = NULL;
95 
96  /* format of a x-ns-css URL is:
97  * x-ns-url:<key>
98  * Where key is an unsigned 32bit integer
99  */
100 
101  path = nsurl_get_component(url, NSURL_PATH);
102  /* The path must exist */
103  if (path == NULL) {
104  return NULL;
105  }
106 
107  key = strtoul(lwc_string_data(path), NULL, 10);
108 
109  lwc_string_unref(path);
110 
111  /* There must be at least one item */
112  if (items == NULL) {
113  return NULL;
114  }
115 
116  item = items;
117  do {
118  if (item->key == key) {
119  found = item;
120  break;
121  }
122 
123  item = item->r_next;
124  } while (item != items);
125 
126  /* We must have found the item */
127  if (found == NULL) {
128  return NULL;
129  }
130 
131  ctx = calloc(1, sizeof(*ctx));
132  if (ctx == NULL)
133  return NULL;
134 
135  ctx->parent_fetch = parent_fetch;
136  ctx->url = nsurl_ref(url);
137  ctx->item = found;
138 
139  RING_INSERT(ring, ctx);
140 
141  return ctx;
142 }
143 
144 static bool html_css_fetcher_start(void *ctx)
145 {
146  return true;
147 }
148 
149 static void html_css_fetcher_free(void *ctx)
150 {
151  html_css_fetcher_context *c = ctx;
152 
153  nsurl_unref(c->url);
154  if (c->item != NULL) {
156  dom_string_unref(c->item->data);
157  RING_REMOVE(items, c->item);
158  free(c->item);
159  }
160  RING_REMOVE(ring, c);
161  free(ctx);
162 }
163 
164 static void html_css_fetcher_abort(void *ctx)
165 {
166  html_css_fetcher_context *c = ctx;
167 
168  /* To avoid the poll loop having to deal with the fetch context
169  * disappearing from under it, we simply flag the abort here.
170  * The poll loop itself will perform the appropriate cleanup.
171  */
172  c->aborted = true;
173 }
174 
177 {
178  c->locked = true;
180  c->locked = false;
181 }
182 
183 static void html_css_fetcher_poll(lwc_string *scheme)
184 {
185  fetch_msg msg;
186  html_css_fetcher_context *c, *next;
187 
188  if (ring == NULL) return;
189 
190  /* Iterate over ring, processing each pending fetch */
191  c = ring;
192  do {
193  /* Ignore fetches that have been flagged as locked.
194  * This allows safe re-entrant calls to this function.
195  * Re-entrancy can occur if, as a result of a callback,
196  * the interested party causes fetch_poll() to be called
197  * again.
198  */
199  if (c->locked == true) {
200  next = c->r_next;
201  continue;
202  }
203 
204  /* Only process non-aborted fetches */
205  if (c->aborted) {
206  /* Nothing to do */
207  assert(c->locked == false);
208  } else if (c->item != NULL) {
209  char header[4096];
210 
212 
213  /* Any callback can result in the fetch being aborted.
214  * Therefore, we _must_ check for this after _every_
215  * call to html_css_fetcher_send_callback().
216  */
217  snprintf(header, sizeof header,
218  "Content-Type: text/css; charset=utf-8");
219  msg.type = FETCH_HEADER;
220  msg.data.header_or_data.buf = (const uint8_t *) header;
221  msg.data.header_or_data.len = strlen(header);
223 
224  if (c->aborted == false) {
225  snprintf(header, sizeof header,
226  "Content-Length: %"PRIsizet,
227  dom_string_byte_length(c->item->data));
228  msg.type = FETCH_HEADER;
229  msg.data.header_or_data.buf =
230  (const uint8_t *) header;
231  msg.data.header_or_data.len = strlen(header);
233  }
234 
235  if (c->aborted == false) {
236  snprintf(header, sizeof header,
237  "X-NS-Base: %.*s",
238  (int) nsurl_length(c->item->base_url),
239  nsurl_access(c->item->base_url));
240  msg.type = FETCH_HEADER;
241  msg.data.header_or_data.buf =
242  (const uint8_t *) header;
243  msg.data.header_or_data.len = strlen(header);
245  }
246 
247  if (c->aborted == false) {
248  msg.type = FETCH_DATA;
249  msg.data.header_or_data.buf =
250  (const uint8_t *)
251  dom_string_data(c->item->data);
252  msg.data.header_or_data.len =
253  dom_string_byte_length(c->item->data);
255  }
256 
257  if (c->aborted == false) {
258  msg.type = FETCH_FINISHED;
260  }
261  } else {
262  NSLOG(netsurf, INFO, "Processing of %s failed!",
263  nsurl_access(c->url));
264 
265  /* Ensure that we're unlocked here. If we aren't,
266  * then html_css_fetcher_process() is broken.
267  */
268  assert(c->locked == false);
269  }
270 
271  /* Compute next fetch item at the last possible moment as
272  * processing this item may have added to the ring.
273  */
274  next = c->r_next;
275 
278 
279  /* Advance to next ring entry, exiting if we've reached
280  * the start of the ring or the ring has become empty
281  */
282  } while ( (c = next) != ring && ring != NULL);
283 }
284 
285 /* exported interface documented in html_internal.h */
287 {
288  const struct fetcher_operation_table html_css_fetcher_ops = {
290  .acceptable = html_css_fetcher_can_fetch,
291  .setup = html_css_fetcher_setup,
292  .start = html_css_fetcher_start,
293  .abort = html_css_fetcher_abort,
294  .free = html_css_fetcher_free,
295  .poll = html_css_fetcher_poll,
296  .finalise = html_css_fetcher_finalise
297  };
298 
299  return fetcher_add(lwc_string_ref(corestring_lwc_x_ns_css),
300  &html_css_fetcher_ops);
301 }
302 
303 /* exported interface documented in html_internal.h */
304 nserror
306 {
307  html_css_fetcher_item *item = malloc(sizeof(*item));
308 
309  if (item == NULL) {
310  return NSERROR_NOMEM;
311  }
312 
313  *key = item->key = current_key++;
314  item->data = dom_string_ref(data);
315  item->base_url = nsurl_ref(base_url);
316 
317  RING_INSERT(items, item);
318 
319  return NSERROR_OK;
320 }
static void html_css_fetcher_poll(lwc_string *scheme)
nserror fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops)
Register a fetcher for a scheme.
Definition: fetch.c:358
struct fetch_msg::@121::@122 header_or_data
struct html_css_fetcher_context * r_prev
static void html_css_fetcher_free(void *ctx)
nserror html_css_fetcher_register(void)
Register the fetcher for the pseudo x-ns-css scheme.
Interface to utility string handling.
Memory exhaustion.
Definition: errors.h:32
static html_css_fetcher_item * items
static uint32_t current_key
Fetch POST multipart data.
Definition: fetch.h:99
static void html_css_fetcher_finalise(lwc_string *scheme)
#define RING_INSERT(ring, element)
Insert the given item into the specified ring.
Definition: ring.h:40
struct html_css_fetcher_context * r_next
Ring list structure.
html_css_fetcher_item * item
nserror
Enumeration of error codes.
Definition: errors.h:29
static bool html_css_fetcher_initialise(lwc_string *scheme)
void fetch_remove_from_queues(struct fetch *fetch)
remove a queued fetch
Definition: fetch.c:808
static bool html_css_fetcher_can_fetch(const nsurl *url)
struct html_css_fetcher_context html_css_fetcher_context
Useful interned string pointers (interface).
Fetcher operations API.
Definition: fetchers.h:49
Private data for text/html content.
struct html_css_fetcher_item html_css_fetcher_item
No error.
Definition: errors.h:30
#define PRIsizet
c99 standard printf formatting for size_t type
Definition: inttypes.h:53
bool(* initialise)(lwc_string *scheme)
The initialiser for the fetcher.
Definition: fetchers.h:55
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:115
static void html_css_fetcher_abort(void *ctx)
#define RING_REMOVE(ring, element)
Remove the given element from the specified ring.
Definition: ring.h:53
void fetch_set_http_code(struct fetch *fetch, long http_code)
set the http code of a fetch
Definition: fetch.c:835
void fetch_free(struct fetch *f)
Free a fetch structure and associated resources.
Definition: fetch.c:589
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
Netsurf additional integer type formatting macros.
static html_css_fetcher_context * ring
static bool html_css_fetcher_start(void *ctx)
nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url, uint32_t *key)
Interface for fetchers factory.
nsurl * nsurl_ref(nsurl *url)
Increment the reference count to a NetSurf URL object.
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821
size_t nsurl_length(const nsurl *url)
Find the length of a NetSurf URL object&#39;s URL, as returned by nsurl_access.
Interface to a number of general purpose functionality.
Information for a single fetch.
Definition: fetch.c:89
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
Fetcher message data.
Definition: fetch.h:72
Fetching of data from a URL (interface).
static void html_css_fetcher_send_callback(const fetch_msg *msg, html_css_fetcher_context *c)
fetch_msg_type type
Definition: fetch.h:73
void fetch_send_callback(const fetch_msg *msg, struct fetch *fetch)
send message to fetch
Definition: fetch.c:798
struct html_css_fetcher_item * r_next
NetSurf URL handling (interface).
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
struct html_css_fetcher_item * r_prev
union fetch_msg::@121 data
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
static void * html_css_fetcher_setup(struct fetch *parent_fetch, nsurl *url, bool only_2xx, bool downgrade_tls, const char *post_urlenc, const struct fetch_multipart_data *post_multipart, const char **headers)