~ubuntu-branches/debian/sid/tickr/sid

« back to all changes in this revision

Viewing changes to src/tickr/tickr_http.c

  • Committer: Package Import Robot
  • Author(s): Emmanuel Thomas-Maurin
  • Date: 2012-06-04 14:23:24 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20120604142324-j6ycu0cw6vvoahhy
Tags: 0.6.1-1
* Add: 'quick setup' thing (in tickr_quicksetup.c) which is launched
  at program startup if config file doesn't exist.

* Little improvements in layout of 'feed picker win' and 'preferences
  win'.

* Fix a segfault that happens when trying to export params and no
  config file exists yet.

* Make several windows that should not be resized by user, unresizable.

* Fix Launchpad bug #1007346: When 'window always-on-top' is disabled,
  'visible on all user desktops' stops working.

* If mouse wheel scrolling applies to speed (or feed), then Ctrl +
  mouse wheel scrolling applies to feed (or speed.)

* No real code changes in libetm, only in comments, so no need for a
  new version number.

* Update tickr_helptext.c and tickr.1 (man page.)

* Add new cli option 'no-ui' (similar to 'instance-id') used by new
  IF_UI_ALLOWED macro and remove all #if USE_GUI occurences.

* In tickr_list.c, free listfname before using it. Fixed by swapping 2
  lines:
    warning(FALSE, 4, "Can't save URL list ", listfname, ...);
    l_str_free(listfname);

* Use/add #define
    FONT_MAXLEN         68
    ARBITRARY_TASKBAR_HEIGHT    25
  to replace a few 'magic' numeric values.

* Rename: rss_title/description(_delimiter) ->
    item_title/description(_delimiter)
  then add new param: feed_title(_delimiter). Now we have:
  feed title / item title / item description.

* Use table in resource properties window.

* Fix a bug in f_list_load_from_file() in tickr_list.c which
  uncorrectly retrieves any feed title string containing TITLE_TAG_CHAR
  when TITLE_TAG_CHAR has not been removed from string first, for
  instance: 'NYT > World' -> ' World'.

* New param: disable left-click.

* Add 'check for updates' feature.

* Launch 'import OPML file' if feed list doesn't exist.

* Remove code changing get_params()->disable_popups value in
    START/END_PAUSE_TICKER_WHILE_OPENING
  macros which prevents this setting to be saved and add
    START/END_PAUSE_TICKER_ENABLE_POPUPS_WHILE_OPENING
  new macros. Which ones to use depends on context.

* Move:
    #ifdef G_OS_WIN32
    extern FILE *stdout_fp, *stderr_fp;
    #endif
  from *.c into tickr.h.

* Default always-on-top setting changed to 'n' (so that tickr is not
  intrusive by default.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
#include "tickr.h"
20
20
 
21
 
#ifdef G_OS_WIN32
22
 
extern FILE     *stdout_fp, *stderr_fp;
23
 
#endif
24
 
 
25
 
/* are these values ok? */
 
21
/* Are these values OK ? */
26
22
#define HTTP_REQUEST_MAXLEN             (8 * 1024 - 1)
27
23
#define HTTP_HEADER_FIELD_MAXLEN        (2 * 1024 - 1)
28
24
#define MAX_HTTP_REDIRECT               8
32
28
#define TAB                             '\x09'
33
29
 
34
30
/* S_MOD -> true in multiple selection mode / false otherwise */
35
 
#define S_MOD           (get_ticker_env()->selection_mode == MULTIPLE)
 
31
#define S_MOD   (get_ticker_env()->selection_mode == MULTIPLE)
36
32
 
37
 
static void remove_chunk_info(char **response)
 
33
void remove_chunk_info(char **response)
38
34
{
39
35
        char    *response2;
40
36
        int     i, j;
52
48
        *response = response2;
53
49
}
54
50
 
55
 
/* 'quickly check feed format' (xml/rss2.0/atom), get shift to beginnig
56
 
 * and cut off trailing part */
 
51
/* 'Quickly check feed format' (xml/rss2.0/atom), get shift to beginnig
 
52
 * and cut off trailing part. */
57
53
static int format_quick_check(char *response, int *shift)
58
54
{
59
55
        int     i;
60
56
 
61
 
        /* this may return false positives so disabled
 
57
        /* This may return false positives so disabled
62
58
        if (strcmp(get_http_header_value("Content-Type", response), "text/xml") != 0)
63
59
                return FEED_FORMAT_ERROR;*/
64
60
        i = 0;
95
91
        return OK;
96
92
}
97
93
 
98
 
/* get host from url but if connecting through proxy */
 
94
/* Get host from url but if connecting through proxy */
99
95
int connect_with_url(sockt *sock, char *url)
100
96
{
101
97
        char            host[FILE_NAME_MAXLEN + 1];
112
108
                        warning(S_MOD, 2, url, ":\nHTTPS protocol not currently supported");
113
109
                        return HTTP_UNSUPPORTED_SCHEME;
114
110
                } else if (strcmp(get_scheme_from_url(url), "file") == 0)
115
 
                        ;/* do nothing here */
 
111
                        ;/* Do nothing here */
116
112
                else if (get_scheme_from_url(url)[0] == '\0') {
117
113
                        warning(S_MOD, 2, "No scheme found in URL: ", url);
118
114
                        return HTTP_UNSUPPORTED_SCHEME;
122
118
                        return HTTP_UNSUPPORTED_SCHEME;
123
119
                }
124
120
        } else {
125
 
                /* connect via proxy */
 
121
                /* Connect via proxy */
126
122
                str_n_cpy(host, get_proxy_host(), FILE_NAME_MAXLEN);
127
123
                str_n_cpy(port_num, get_proxy_port(), PORT_STR_MAXLEN);
128
124
        }
148
144
}
149
145
 
150
146
/* ***********************************
151
 
 *   TODO: DOCUMENT BETTER THIS FUNC
 
147
 *   TODO: BETTER DOCUMENT THIS FUNC
152
148
 * ***********************************/
153
 
/* we replace resrc->id with modified url and file_name = downloaded resource
154
 
 * maxlen of file_name, url, new_url = FILE_NAME_MAXLEN */
 
149
/* We replace resrc->id with modified url and file_name = downloaded resource.
 
150
 * Max length of file_name, url, and new_url = FILE_NAME_MAXLEN. */
155
151
int fetch_resource(const char *resrc_id, const char *file_name, char *url)
156
152
{
157
153
        sockt   sock;
225
221
        } else
226
222
                return i;
227
223
        while (TRUE) {
228
 
                /* status checked here are those returned by get_http_response()
229
 
                 * so we must make sure they all match */
 
224
                /* Status checked here are those returned by get_http_response()
 
225
                 * so we must make sure they all match. */
230
226
                if (status == HTTP_CONTINUE) {
231
227
                        free2(response);
232
228
                        status = get_http_response(sock, "GET", "", url, &new_url, &response, &recv_status);
241
237
                        return status;
242
238
                } else if (status == OK) {
243
239
                        if (strcmp(get_http_header_value("Transfer-Encoding", response), "chunked") == 0) {
244
 
                                /* chunked transfer encoding */
 
240
                                /* Chunked transfer encoding */
245
241
                                remove_chunk_info(&response);
246
242
                        } else if ((content_length = atoi(get_http_header_value("Content-Length", response))) > 0) {
247
243
                                /* 'Content-Length' = length of entity body is mandatory
248
 
                                 * but if 'Transfer-Encoding: chunked' */
249
 
                                /* do nothing */
 
244
                                 * but if 'Transfer-Encoding: chunked'. */
 
245
                                /* Do nothing */
250
246
                        } else {
251
 
#ifdef VERBOSE_OUTPUT           /* only if verbose because notification only, nothing done */
 
247
#ifdef VERBOSE_OUTPUT           /* Only if verbose because notification only, nothing done. */
252
248
                                fprintf(STD_ERR, "No 'Transfer-Encoding' nor 'Content-Length' "
253
249
                                        "header field in HTTP response\n");
254
250
#endif
255
251
                        }
256
 
                        /* quickly 'check format' (xml and rss2.0/atom stuff),
257
 
                         * shift to beginnig and cut off trailing part */
 
252
                        /* Quickly 'check format' (xml and rss2.0/atom stuff),
 
253
                         * shift to beginnig and cut off trailing part. */
258
254
                        if ((j = format_quick_check(response, &i)) != OK) {
259
255
                                free2(response);
260
256
                                return j;
261
257
                        }
262
 
                        /* if ok, save to dump file */
 
258
                        /* If OK, save to dump file. */
263
259
                        if ((fp = g_fopen(file_name, "wb+")) != NULL) {
264
260
                                fprintf(fp, "%s", response + i);
265
261
                                fclose(fp);
311
307
                        current_feed();
312
308
                        return status;
313
309
                } else if (status == HTTP_PROXY_AUTH_REQUIRED) {
314
 
                        /* proxy authentication */
 
310
                        /* Proxy authentication */
315
311
                        free2(response);
316
312
                        CLOSE_SOCK(sock);
317
313
                        if (get_use_proxy_auth()) {
424
420
        }
425
421
}
426
422
 
427
 
/* rq_str may contain header fields(s) separated and ended by "\r\n" */
 
423
/* 'rq_str' may contain header fields(s) separated and ended by "\r\n" */
428
424
const char *build_http_request(const char *method, const char *path,\
429
425
                const char *host, const char* rq_str)
430
426
{
431
427
        static char     str[HTTP_REQUEST_MAXLEN + 1];
432
428
 
433
429
        snprintf(str, HTTP_REQUEST_MAXLEN,
434
 
                "%s %s HTTP/1.1\r\n"    /* start line with method and path */
435
 
                "Host: %s\r\n"          /* mandatory host header field */
 
430
                "%s %s HTTP/1.1\r\n"    /* Start line with method and path */
 
431
                "Host: %s\r\n"          /* Mandatory host header field */
436
432
                "User-Agent: "APP_NAME"-"APP_VERSION_NUMBER"\r\n"
437
433
                "%s\r\n",               /* optional extra header field(s) */
438
434
                method, path, host, rq_str);
440
436
}
441
437
 
442
438
/*
443
 
 * rq_str may contain header field(s) separated and ended by "\r\n"
444
 
 * must 'free2' response afterwards
 
439
 * 'rq_str' may contain header field(s) separated and ended by "\r\n".
 
440
 * Must 'free2' response afterwards.
445
441
 */
446
442
int get_http_response(sockt sock, const char *rq_method, const char *rq_str,
447
443
        const char *rq_url, char **new_rq_url, char **response, int *recv_status)
455
451
        *response = NULL;
456
452
        str = (char *)build_http_request(
457
453
                rq_method,
458
 
                (get_use_proxy() ? rq_url : get_path_from_url(rq_url)), /* path or full (absolute) url if using proxy */
 
454
                (get_use_proxy() ? rq_url : get_path_from_url(rq_url)), /* Path or full (absolute) url if using proxy */
459
455
                /* is that correct when using proxy? */
460
456
                get_host_from_url(rq_url),
461
457
                rq_str);
467
463
                                return HTTP_SWITCH_PROTO;
468
464
                        else if (status_code == 200)
469
465
                                return OK;
470
 
                        else if (       /* 'multiple choices' */
 
466
                        else if (       /* 'Multiple choices' */
471
467
                                        status_code == 300 ||\
472
 
                                        /* 'moved permanently' */
 
468
                                        /* 'Moved permanently' */
473
469
                                        status_code == 301 ||\
474
 
                                        /* 'found' */
 
470
                                        /* 'Found' */
475
471
                                        status_code == 302 ||\
476
 
                                        /* 'see other' */
 
472
                                        /* 'See other' */
477
473
                                        status_code == 303 ||\
478
 
                                        /* 'not modified' */
 
474
                                        /* 'Not modified' */
479
475
                                        status_code == 304 ||\
480
 
                                        /* 'moved temporarily' */
 
476
                                        /* 'Moved temporarily' */
481
477
                                        status_code == 307) {
482
478
                                str_n_cpy(location, get_http_header_value("Location", *response),
483
479
                                        FILE_NAME_MAXLEN);
484
 
                                return HTTP_MOVED;      /* must use the new url in 'Location' */
 
480
                                return HTTP_MOVED;      /* Must use the new url in 'Location' */
485
481
                        } else if (status_code == 305)
486
482
                                return HTTP_USE_PROXY;
487
483
                        else if (status_code == 400)
506
502
                return SEND_ERROR;
507
503
}
508
504
 
509
 
/* return -1 if error */
 
505
/* Return -1 if error */
510
506
int get_http_status_code(const char *response)
511
507
{
512
508
        char    status_code[4];
527
523
        return atoi(status_code);
528
524
}
529
525
 
530
 
/* get header_value as string (empty one if header name not found) */
 
526
/* Get header_value as string (empty one if header name not found) */
531
527
const char *get_http_header_value(const char *header_name, const char *response)
532
528
{
533
529
        static char     header_value[1024];
562
558
        return (const char *)header_value;
563
559
}
564
560
 
565
 
/* return 0 if none found */
 
561
/* Return 0 if none found */
566
562
int go_after_next_cr_lf(const char *response)
567
563
{
568
564
        int     i = 0;
575
571
                return 0;
576
572
}
577
573
 
578
 
/* return 0 if none found */
 
574
/* Return 0 if none found */
579
575
int go_after_next_empty_line(const char *response)
580
576
{
581
577
        int     i = 0;
588
584
                return 0;
589
585
}
590
586
 
591
 
/* response must point to chunk size hexa str or preceeding space(s)
592
 
 * return -1 if invalid chunk size format (ie not an hexa str) */
 
587
/* 'response' must point to chunk size hexa str or preceeding space(s).
 
588
 * Return -1 if invalid chunk size format (ie not an hexa str). */
593
589
int get_http_chunk_size(const char *response)
594
590
{
595
591
        char    size_str[32], *tailptr;
617
613
 
618
614
/*
619
615
 * 'http://www.sth1.org/sth2/sth2.xml' -> 'http'
620
 
 * (expect one scheme in url, return empty str if none)
 
616
 * (expect one scheme in url, return empty str if none).
621
617
 */
622
618
const char *get_scheme_from_url(const char* url)
623
619
{
635
631
 
636
632
/*
637
633
 * 'http://www.sth1.org/sth2/sth2.xml' -> 'www.sth1.org'
638
 
 * (expect one scheme in url, return empty str if none)
 
634
 * (expect one scheme in url, return empty str if none).
639
635
 */
640
636
const char *get_host_from_url(const char* url)
641
637
{
657
653
 
658
654
/*
659
655
 * 'http://www.sth1.org/sth2/sth2.xml' -> '/sth2/sth2.xml'
660
 
 * (expect one scheme in url, return empty str if none)
 
656
 * (expect one scheme in url, return empty str if none).
661
657
 */
662
658
const char *get_path_from_url(const char* url)
663
659
{