~ubuntu-branches/ubuntu/precise/gtimer/precise-proposed

« back to all changes in this revision

Viewing changes to http.c

  • Committer: Bazaar Package Importer
  • Author(s): Taylor LeMasurier-Wren
  • Date: 2011-08-06 03:07:30 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110806030730-9wtxfpgsf1h4ulac
Tags: 2.0.0-1
* Update watch file
* Update debhelper compatibilty to V7 (significantly clean up packaging)
* New Upstream Release (Closes: #575666: RFP: GTimer -- GTK-based tool for
  timing tasks)
* Initial release. (Closes: #636822: ITP: gtimer -- GTK-based X11 task
  timer)
* Switch to dpkg-source 3.0 (quilt) format

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * GTimer
 
3
 *
 
4
 * Copyright:
 
5
 *      (C) 1999 Craig Knudsen, cknudsen@cknudsen.com
 
6
 *      See accompanying file "COPYING".
 
7
 * 
 
8
 *      This program is free software; you can redistribute it and/or
 
9
 *      modify it under the terms of the GNU General Public License
 
10
 *      as published by the Free Software Foundation; either version 2
 
11
 *      of the License, or (at your option) any later version.
 
12
 * 
 
13
 *      This program is distributed in the hope that it will be useful,
 
14
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *      GNU General Public License for more details.
 
17
 * 
 
18
 *      You should have received a copy of the GNU General Public License
 
19
 *      along with this program; if not, write to the
 
20
 *      Free Software Foundation, Inc., 59 Temple Place,
 
21
 *      Suite 330, Boston, MA  02111-1307, USA
 
22
 *
 
23
 * Description:
 
24
 *      Helps you keep track of time spent on different tasks.
 
25
 *
 
26
 * Author:
 
27
 *      Craig Knudsen, cknudsen@cknudsen.com, http://www.cknudsen.com
 
28
 *
 
29
 * Home Page:
 
30
 *      http://www.cknudsen.com/gtimer/
 
31
 *
 
32
 * History:
 
33
 *      19-May-1999     Created (based on an 1995 app I wrote)
 
34
 *
 
35
 ****************************************************************************/
 
36
 
 
37
 
 
38
#include <stdio.h>
 
39
#include <stdlib.h>
 
40
#include <string.h>
 
41
#include <ctype.h>
 
42
#include <errno.h>
 
43
#include <sys/time.h>
 
44
#include <sys/types.h>
 
45
#include <sys/stat.h>
 
46
#ifdef AIX
 
47
#include <sys/select.h>
 
48
#endif
 
49
#include <sys/ioctl.h>
 
50
#ifdef WIN32
 
51
#include <winsock.h>    /* winsock API */
 
52
#else
 
53
#include <unistd.h>
 
54
#include <netdb.h>      /* for gethostbyaddr() */
 
55
#include <sys/socket.h>
 
56
#include <netinet/in.h>
 
57
#endif
 
58
#include <fcntl.h>
 
59
#include <time.h>
 
60
 
 
61
#include "project.h"
 
62
#include "task.h"
 
63
#include "gtimer.h"
 
64
 
 
65
#include "tcpt.h"
 
66
#include "http.h"
 
67
 
 
68
#ifdef GTIMER_MEMDEBUG
 
69
#include "memdebug/memdebug.h"
 
70
#endif
 
71
 
 
72
 
 
73
static char *my_strtok (
 
74
#ifndef _NO_PROTO
 
75
  char *ptr1, char *tok
 
76
#endif
 
77
);
 
78
 
 
79
 
 
80
/*
 
81
** Max number of bytes to read at once.
 
82
*/
 
83
#define MAX_READ_SIZE           1024
 
84
 
 
85
/*
 
86
** Structure for states.
 
87
*/
 
88
typedef struct _httpRequest {
 
89
  sockfd connection;                    /* connection to server */
 
90
  char *request;                        /* text message to send */
 
91
  httpError (*read_function)();         /* read function */
 
92
#ifdef _NO_PROTO
 
93
  void (*callback)();                   /* callback when results received */
 
94
#else
 
95
  void (*callback)(char *);             /* callback when results received */
 
96
#endif
 
97
#ifdef _NO_PROTO
 
98
  void (*gen_callback)();               /* callback when results received */
 
99
#else
 
100
  void (*gen_callback)(char *,int);     /* callback when results received */
 
101
#endif
 
102
  int sent;                             /* has request been sent */
 
103
  char *data_read;                      /* data that was read */
 
104
  int data_len;                         /* size of above data */
 
105
  int content_length;                   /* length according to header */
 
106
  int pass;                             /* no. reads done */
 
107
} httpRequest;
 
108
 
 
109
#define MAX_REQUESTS_QUEUED     2048
 
110
 
 
111
static char http_other_error[256];
 
112
static httpRequest *requests[MAX_REQUESTS_QUEUED];
 
113
static int num_requests = 0;
 
114
static char *http_proxy = NULL;
 
115
static char http_proxy_string[1024];
 
116
static int http_proxy_port;
 
117
 
 
118
 
 
119
static char *user_agent () {
 
120
  static char ret[100];
 
121
 
 
122
  sprintf ( ret, "GTimer/%s", GTIMER_VERSION );
 
123
  return ( ret );
 
124
}
 
125
 
 
126
/*
 
127
** Local functions.
 
128
*/
 
129
static char *httpTruncateHeader (
 
130
#ifndef _NO_PROTO
 
131
  char *text,
 
132
  int *len
 
133
#endif
 
134
);
 
135
static httpError httpReadGet (
 
136
#ifndef _NO_PROTO
 
137
  httpRequest *request
 
138
#endif
 
139
);
 
140
static httpError httpReadGetArticles (
 
141
#ifndef _NO_PROTO
 
142
  httpRequest *request
 
143
#endif
 
144
);
 
145
static httpError httpReadGetAds (
 
146
#ifndef _NO_PROTO
 
147
  httpRequest *request
 
148
#endif
 
149
);
 
150
static httpError httpReadList (
 
151
#ifndef _NO_PROTO
 
152
  httpRequest *request
 
153
#endif
 
154
);
 
155
static httpError httpReadGetUserId (
 
156
#ifndef _NO_PROTO
 
157
  httpRequest *request
 
158
#endif
 
159
);
 
160
static httpError httpReadGetSessionId (
 
161
#ifndef _NO_PROTO
 
162
  httpRequest *request
 
163
#endif
 
164
);
 
165
static httpError httpSendRequest (
 
166
#ifndef _NO_PROTO
 
167
  httpRequest *request
 
168
#endif
 
169
);
 
170
static char *encode_for_use_in_url (
 
171
#ifndef _NO_PROTO
 
172
  char *str
 
173
#endif
 
174
);
 
175
 
 
176
 
 
177
 
 
178
 
 
179
 
 
180
/*
 
181
** URL-encode a string
 
182
** See RFC 1738 (http://andrew2.andrew.cmu.edu/rfc/rfc1738.html)
 
183
** Caller should free result.
 
184
*/
 
185
static char *encode_for_use_in_url ( str )
 
186
char *str;
 
187
{
 
188
  char *ret, *ptr1, *ptr2, *ptr3;
 
189
  static char unsafe_chars[] = {
 
190
    ' ', '{', '}', '|', '/', '\\', '^', '~', '[', ']', '`', '%', '<', '>', '"', '#', ')', '(', '\0',
 
191
  };
 
192
  int unsafe;
 
193
 
 
194
  /* just to be safe... */
 
195
  ret = (char *) malloc ( strlen ( str ) * 3 + 1 );
 
196
 
 
197
  for ( ptr1 = str, ptr2 = ret; *ptr1 != '\0'; ptr1++ ) {
 
198
    unsafe = 0;
 
199
    /* is unsafe??? */
 
200
    for ( ptr3 = unsafe_chars; *ptr3 != '\0'; ptr3++ ) {
 
201
      if ( *ptr3 == *ptr1 ) {
 
202
        unsafe = 1;
 
203
        break;
 
204
      }
 
205
    }
 
206
/*
 
207
    if ( ! unsafe ) {
 
208
      if ( ( (unsigned int)*ptr1 < 0x80 || (unsigned int)*ptr1 > 0xFF ) ||
 
209
        ( (unsigned int)*ptr1 >= 0x00 && (unsigned int)*ptr1 <= 0x1F ) ||
 
210
        ( (unsigned int)*ptr1 == 0x7F ) )
 
211
        unsafe = 1;
 
212
    }
 
213
*/
 
214
    if ( unsafe ) {
 
215
      sprintf ( ptr2, "%%%02X", (unsigned int)*ptr1 );
 
216
      ptr2 += 3;
 
217
    }
 
218
    else {
 
219
      *ptr2 = *ptr1;
 
220
      ptr2++;
 
221
    }
 
222
  }
 
223
  *ptr2 = '\0';
 
224
 
 
225
  return ( ret );
 
226
}
 
227
 
 
228
 
 
229
 
 
230
void httpEnableProxy ( server, port )
 
231
char *server;
 
232
int port;
 
233
{
 
234
  if ( http_proxy )
 
235
    free ( http_proxy );
 
236
  http_proxy = (char *) malloc ( strlen ( server ) + 1 );
 
237
  strcpy ( http_proxy, server );
 
238
  http_proxy_port = port;
 
239
}
 
240
 
 
241
 
 
242
void httpDisableProxy ()
 
243
{
 
244
  if ( http_proxy )
 
245
    free ( http_proxy );
 
246
  http_proxy_string[0] = '\0';
 
247
  http_proxy = NULL;
 
248
}
 
249
 
 
250
 
 
251
/*
 
252
** Put a request onto the end of the queue.
 
253
** Current request is always reqeusts[0].
 
254
*/
 
255
httpError httpEnqueueRequest ( connection, msg, read_function, callback,
 
256
  gen_callback )
 
257
sockfd connection;
 
258
char *msg;
 
259
#ifdef _NO_PROTO
 
260
httpError (*read_function)();
 
261
void (*callback)();
 
262
void (*gen_callback)();
 
263
#else
 
264
httpError (*read_function)(sockfd);
 
265
void (*callback)(char *);
 
266
void (*gen_callback)(char *,int);
 
267
#endif
 
268
{
 
269
  httpRequest *request;
 
270
 
 
271
  if ( num_requests >= MAX_REQUESTS_QUEUED - 1 ) {
 
272
    fprintf ( stderr, "Too many errors...\n" );
 
273
    return ( HTTP_TOO_MANY_REQUESTS );
 
274
  }
 
275
 
 
276
  /* put request at end of queue. */
 
277
  request = (httpRequest *) malloc ( sizeof ( httpRequest ) );
 
278
  memset ( request, '\0', sizeof ( httpRequest ) );
 
279
  if ( msg ) {
 
280
    request->request = (char *) malloc ( strlen ( msg ) + 1 );
 
281
    strcpy ( request->request, msg );
 
282
    request->connection = connection;
 
283
  }
 
284
  else {
 
285
    /* NULL msg indicates no message to send */
 
286
    request->request = NULL;
 
287
    request->sent = 1;
 
288
  }
 
289
  request->connection = connection;
 
290
  request->read_function = read_function;
 
291
  request->callback = callback;
 
292
  request->gen_callback = gen_callback;
 
293
  request->data_read = NULL;
 
294
  requests[num_requests++] = request;
 
295
 
 
296
  /* now send the request if this is the only request */
 
297
  if ( num_requests == 1 ) {
 
298
    httpSendRequest ( requests[0] );
 
299
  }
 
300
 
 
301
  return ( HTTP_NO_ERROR );
 
302
}
 
303
 
 
304
 
 
305
 
 
306
/*
 
307
** Send a request to the server.
 
308
** This should not be called directly, only from httpDequeueRequest and
 
309
** httpEnqueueRequest.
 
310
*/
 
311
static httpError httpSendRequest ( request )
 
312
httpRequest *request;
 
313
{
 
314
  int rval;
 
315
 
 
316
  if ( ! request->sent ) {
 
317
    rval = send ( request->connection, request->request,
 
318
      strlen ( request->request ), 0 );
 
319
 
 
320
    request->sent = 1;
 
321
 
 
322
    if ( rval >= 0 )
 
323
      return ( HTTP_NO_ERROR );
 
324
    else
 
325
      return ( HTTP_SOCKET_ERROR );
 
326
  }
 
327
  else
 
328
    return ( HTTP_NO_ERROR );
 
329
}
 
330
 
 
331
 
 
332
 
 
333
/*
 
334
** Remove the most recent request from the queue.
 
335
** It is not an error to call this function with nothing in the queue.
 
336
*/
 
337
httpError httpDequeueRequest ()
 
338
{
 
339
  int loop;
 
340
 
 
341
  if ( num_requests ) {
 
342
    if ( requests[0]->data_read )
 
343
      free ( requests[0]->data_read );
 
344
    if ( requests[0]->request )
 
345
      free ( requests[0]->request );
 
346
    free ( requests[0] );
 
347
    /* move each request up one slot */
 
348
    for ( loop = 1; loop < num_requests; loop++ )
 
349
      requests[loop-1] = requests[loop];
 
350
    num_requests--;
 
351
  }
 
352
 
 
353
  if ( num_requests )
 
354
    httpSendRequest ( requests[0] );
 
355
 
 
356
  return ( HTTP_NO_ERROR );
 
357
}
 
358
 
 
359
 
 
360
 
 
361
/*
 
362
** Calling app calls this when select() indicates data is ready to be
 
363
** read on socket.  This will figure out where we left off and
 
364
** continue from there.
 
365
*/
 
366
httpError httpProcessRead ( connection )
 
367
sockfd connection;
 
368
{
 
369
  int loop;
 
370
  int num = -1;
 
371
 
 
372
  for ( loop = 0; loop < num_requests; loop++ ) {
 
373
    if ( requests[loop]->connection == connection ) {
 
374
      num = loop;
 
375
      break;
 
376
    }
 
377
  }
 
378
 
 
379
  if ( num < 0 )
 
380
    return ( HTTP_NO_REQUESTS );
 
381
 
 
382
  return ( requests[loop]->read_function ( requests[loop] ) );
 
383
}
 
384
 
 
385
 
 
386
 
 
387
/*
 
388
** Connect to an HTTP server.
 
389
** Returns socket file descriptor.
 
390
** Note that this is the one place where we must wait for a response
 
391
** that could cause things to hang a bit.
 
392
*/
 
393
httpError httpOpenConnection ( http_host, port, connection )
 
394
char *http_host;
 
395
int port;
 
396
sockfd *connection;
 
397
{
 
398
  sockfd sock;
 
399
  static struct sockaddr_in server;
 
400
  struct hostent *hp, *gethostbyname ();
 
401
  tcptError ret;
 
402
 
 
403
  memset ( &server, '\0', sizeof ( struct sockaddr_in ) );
 
404
 
 
405
  /* Verify all necessary data is available */
 
406
  if ( ! http_host || ! strlen ( http_host ) )
 
407
    return ( HTTP_INVALID_HOST );
 
408
 
 
409
  if ( http_proxy ) {
 
410
    /* save info for next request */
 
411
    sprintf ( http_proxy_string, "http://%s:%d", http_host, port );
 
412
    /* now change to http proxy */
 
413
    http_host = http_proxy;
 
414
    port = http_proxy_port;
 
415
  }
 
416
 
 
417
  hp = gethostbyname ( http_host );
 
418
 
 
419
  if ( ! hp ) {
 
420
    return ( HTTP_HOST_LOOKUP_FAILED );
 
421
  }
 
422
 
 
423
  /* Init windows winsock DLL */
 
424
  if ( tcptInit () ) {
 
425
    return ( HTTP_SOCKET_ERROR );
 
426
  }
 
427
 
 
428
  sock = socket ( AF_INET, SOCK_STREAM, 0 );
 
429
  if ( sock < 0 ) {
 
430
    tcptCleanup ();
 
431
    return ( HTTP_SOCKET_ERROR );
 
432
  }
 
433
 
 
434
  server.sin_family = AF_INET;
 
435
  memcpy ( (char *)&server.sin_addr, (char*)hp->h_addr, hp->h_length );
 
436
 
 
437
  /* Get HTTP port (80) */
 
438
  if ( port )
 
439
    server.sin_port = htons ( port );
 
440
  else
 
441
    server.sin_port = htons ( HTTP_PORT );
 
442
 
 
443
  if ( ( ret = tcptConnect ( sock, (struct sockaddr *)&server,
 
444
     sizeof ( server ) ) ) ) {
 
445
    strcpy ( http_other_error, tcptErrorString ( ret ) );
 
446
    return ( HTTP_OTHER_ERROR );
 
447
  }
 
448
 
 
449
  /* success.  return socket */
 
450
  *connection = sock;
 
451
 
 
452
  /* Set to non-blocking */
 
453
  /*ioctl ( *connection, FIONBIO, 1 );*/
 
454
 
 
455
  return ( HTTP_NO_ERROR );
 
456
}
 
457
 
 
458
 
 
459
 
 
460
 
 
461
 
 
462
/*
 
463
** Close the connection and remove all requests from the queue.
 
464
*/
 
465
httpError httpKillConnection ( connection )
 
466
sockfd connection;
 
467
{
 
468
  int loop, newnum;
 
469
 
 
470
  /*
 
471
  ** Remove all requests in the queue that reference this connection.
 
472
  */
 
473
  for ( loop = 0, newnum = 0; loop < num_requests; loop++ ) {
 
474
    if ( requests[loop]->connection == connection ) {
 
475
      /* NULL out requests we are killing */
 
476
      if ( requests[loop]->data_read )
 
477
        free ( requests[loop]->data_read );
 
478
      if ( requests[loop]->request )
 
479
        free ( requests[loop]->request );
 
480
      free ( requests[loop] );
 
481
      requests[loop] = NULL;
 
482
    }
 
483
    else {
 
484
      requests[newnum] = requests[loop];
 
485
    }
 
486
  }
 
487
 
 
488
  for ( loop = 0, newnum = 0; loop < num_requests; loop++ ) {
 
489
    if ( requests[loop] && loop != newnum ) {
 
490
      requests[newnum] = requests[loop];
 
491
      requests[loop] = NULL;
 
492
      newnum++;
 
493
    }
 
494
  }
 
495
 
 
496
  num_requests = newnum;
 
497
 
 
498
  closesocket ( connection );
 
499
  return ( HTTP_NO_ERROR );
 
500
}
 
501
 
 
502
 
 
503
 
 
504
/*
 
505
** Do a generic get request.
 
506
*/
 
507
httpError httpGet ( connection, virthost, path, qs_names, qs_values,
 
508
  num, callback )
 
509
sockfd connection;
 
510
char *virthost;
 
511
char *path;
 
512
char *qs_names[];
 
513
char *qs_values[];
 
514
int num;
 
515
#ifdef _NO_PROTO
 
516
void (*callback)();
 
517
#else
 
518
void (*callback)(char *,int);
 
519
#endif
 
520
{
 
521
  char *command, *temp, temp2[256], *ret1, *ret2;
 
522
  int loop;
 
523
 
 
524
  temp = (char *) malloc ( strlen ( path ) + strlen ( http_proxy_string ) +
 
525
    5 );
 
526
  sprintf ( temp, "GET %s%s", http_proxy_string, path );
 
527
  command = (char *) malloc ( strlen ( temp ) + 2 );
 
528
  strcpy ( command, temp );
 
529
  free ( temp );
 
530
  if ( num ) {
 
531
    strcat ( command, "?" );
 
532
    for ( loop = 0; loop < num; loop++ ) {
 
533
      ret1 = encode_for_use_in_url ( qs_names[loop] );
 
534
      ret2 = encode_for_use_in_url ( qs_values[loop] );
 
535
      command = (char *) realloc ( command, strlen ( command ) +
 
536
        strlen ( ret1 ) + strlen ( ret2 ) + 3 );
 
537
      if ( loop )
 
538
        strcat ( command, "&" );
 
539
      strcat ( command, ret1 );
 
540
      strcat ( command, "=" );
 
541
      strcat ( command, ret2 );
 
542
      free ( ret1 );
 
543
      free ( ret2 );
 
544
    }
 
545
  }
 
546
  strcpy ( temp2, " HTTP/1.0\r\n" );
 
547
  strcat ( temp2, "User-Agent: " );
 
548
  strcat ( temp2, user_agent() );
 
549
  strcat ( temp2, "\r\n" );
 
550
  if ( virthost != NULL ) {
 
551
    strcat ( temp2, "Host: " );
 
552
    strcat ( temp2, virthost );
 
553
    strcat ( temp2, "\r\n" );
 
554
  }
 
555
  strcat ( temp2, "\r\n" );
 
556
  command = (char *) realloc ( command, strlen ( command ) +
 
557
    strlen ( temp2 ) + 1 );
 
558
  strcat ( command, temp2 );
 
559
 
 
560
  httpEnqueueRequest ( connection, command, httpReadGet, NULL, callback );
 
561
 
 
562
  return ( HTTP_NO_ERROR );
 
563
}
 
564
 
 
565
static int my_strncasecmp ( str1, str2, len )
 
566
char *str1, *str2;
 
567
int len;
 
568
{
 
569
  char *a1, *a2, *ptr;
 
570
  int ret, loop;
 
571
 
 
572
  a1 = (char *) malloc ( len + 1 );
 
573
  strncpy ( a1, str1, len );
 
574
  a1[len] = '\0';
 
575
  a2 = (char *) malloc ( len + 1 );
 
576
  strncpy ( a2, str2, len );
 
577
  a2[len] = '\0';
 
578
  for ( ptr = a1, loop = 0; *ptr != '\0' && loop < len; loop++, ptr++ )
 
579
    *ptr = toupper ( *ptr );
 
580
  for ( ptr = a2, loop = 0; *ptr != '\0' && loop < len; loop++, ptr++ )
 
581
    *ptr = toupper ( *ptr );
 
582
 
 
583
  ret = strncmp ( a1, a2, len );
 
584
  free ( a1 );
 
585
  free ( a2 );
 
586
 
 
587
  return ( ret );
 
588
}
 
589
 
 
590
static httpError httpReadGet ( request )
 
591
httpRequest *request;
 
592
{
 
593
  int rval;
 
594
  char data[MAX_READ_SIZE], *alldata, *ptr;
 
595
  int len;
 
596
 
 
597
  memset ( data, '\0', MAX_READ_SIZE );
 
598
  rval = recv ( request->connection, data, MAX_READ_SIZE, 0 );
 
599
  if ( rval < 0 )
 
600
    return ( HTTP_SOCKET_ERROR );
 
601
  else if ( rval == 0 ) {
 
602
    /* we are done. */
 
603
    request->gen_callback ( request->data_read, request->data_len );
 
604
    request->gen_callback ( NULL, 0 );
 
605
    httpDequeueRequest ();
 
606
    return ( HTTP_NO_ERROR );
 
607
  }
 
608
  if ( request->data_read ) {
 
609
    alldata = (char *) malloc ( request->data_len + rval );
 
610
    memcpy ( alldata, request->data_read, request->data_len );
 
611
    memcpy ( alldata + request->data_len, data, rval );
 
612
    len = request->data_len + rval;
 
613
  }
 
614
  else {
 
615
    alldata = (char *) malloc ( rval );
 
616
    memcpy ( alldata, data, rval );
 
617
    len = rval;
 
618
  }
 
619
  if ( request->data_read )
 
620
    free ( request->data_read );
 
621
  if ( ! request->content_length ) {
 
622
    request->data_read = httpTruncateHeader ( alldata, &len );
 
623
    if ( request->data_read )
 
624
      request->data_len = len;
 
625
    if ( request->data_read ) {
 
626
      /* complete header found (starts in alldata) */
 
627
      ptr = strtok ( alldata, "\r\n" );
 
628
      while ( ptr ) {
 
629
        if ( strncmp ( ptr, "HTTP/1.0 200", 12 ) == 0 ||
 
630
          strncmp ( ptr, "HTTP/1.1 200", 12 ) == 0 ) {
 
631
          /* ok status. ignore */
 
632
        }
 
633
        else if ( strncmp ( ptr, "HTTP/1.", 7 ) == 0 ) {
 
634
          /* some other status -- error */
 
635
          request->gen_callback ( ptr, strlen ( ptr ) );   /* indicates error */
 
636
          request->gen_callback ( NULL, 0 );        /* indicates error */
 
637
          httpDequeueRequest ();
 
638
          free ( alldata );
 
639
          return ( HTTP_HTTP_ERROR );
 
640
        }
 
641
        else if ( my_strncasecmp ( ptr, "Content-Length:", 15 ) == 0 ) {
 
642
          /* specifies length of content */
 
643
          request->content_length = atoi ( ptr + 15 );
 
644
          break;
 
645
        }
 
646
        else {
 
647
           /* ignore all others.... */
 
648
        }
 
649
        ptr = strtok ( NULL, "\r\n" );
 
650
      }
 
651
    }
 
652
  }
 
653
  else {
 
654
    if ( request->content_length == len ) {
 
655
      /* we're done */
 
656
      request->gen_callback ( alldata, len );
 
657
      request->gen_callback ( NULL, 0 );
 
658
      httpDequeueRequest ();
 
659
      free ( alldata );
 
660
      return ( HTTP_HTTP_ERROR );
 
661
    }
 
662
  }
 
663
 
 
664
  free ( alldata );
 
665
  return ( HTTP_NO_ERROR );
 
666
}
 
667
 
 
668
 
 
669
 
 
670
 
 
671
 
 
672
 
 
673
char *httpErrorString ( num )
 
674
httpError num;
 
675
{
 
676
  static char msg[200];
 
677
 
 
678
  switch ( num ) {
 
679
    case HTTP_NO_ERROR:
 
680
      return ( "No error." );
 
681
    case HTTP_INVALID_HOST:
 
682
      return ( "Unable to resolve server name." );
 
683
    case HTTP_SYSTEM_ERROR:
 
684
      sprintf ( msg, "System error (%d)", errno );
 
685
      return ( msg );
 
686
    case HTTP_SOCKET_ERROR:
 
687
      sprintf ( msg, "System error (%d)", errno );
 
688
      return ( msg );
 
689
    case HTTP_HTTP_ERROR:
 
690
      return ( "HTTP protocol error." );
 
691
    case HTTP_NO_REQUESTS:
 
692
      return ( "No requests on queue." );
 
693
    case HTTP_TOO_MANY_REQUESTS:
 
694
      return ( "Too many requests on queue." );
 
695
    case HTTP_HOST_LOOKUP_FAILED:
 
696
      return ( "Unable to resolve server hostname" );
 
697
    case HTTP_OTHER_ERROR:
 
698
      return ( http_other_error );
 
699
    case HTTP_UNKNOWN_ERROR:
 
700
    default:
 
701
      return ( "Unknown error." );
 
702
  }
 
703
}
 
704
 
 
705
 
 
706
 
 
707
 
 
708
 
 
709
 
 
710
 
 
711
 
 
712
 
 
713
/*
 
714
** Take the given text and truncate after the http header
 
715
*/
 
716
static char *httpTruncateHeader ( text, len )
 
717
char *text;
 
718
int *len;
 
719
{
 
720
  char *ptr;
 
721
  char *ret;
 
722
  char *end_header1 = "\n\n";
 
723
  char *end_header2 = "\r\n\r\n";
 
724
  int loop;
 
725
  int newlen;
 
726
 
 
727
  /* check to see it we've reached the end. */
 
728
  if ( strlen ( text ) < 10 )
 
729
    return ( NULL );
 
730
 
 
731
  /* back up to the last separator */
 
732
  for ( loop = 0, ptr = text; loop < *len; loop++, ptr++ ) {
 
733
    if ( strncmp ( ptr, end_header1, strlen ( end_header1 ) ) == 0 ) {
 
734
      /* end of http header found */
 
735
      *ptr = '\0';
 
736
      ptr += strlen ( end_header1 );
 
737
      newlen = *len - strlen ( text ) - strlen ( end_header1 );
 
738
      ret = (char *) malloc ( newlen );
 
739
      memcpy ( ret, ptr, newlen );
 
740
      *len = newlen;
 
741
      return ( ret );
 
742
    }
 
743
    else if ( strncmp ( ptr, end_header2, strlen ( end_header2 ) ) == 0 ) {
 
744
      /* end of http header found */
 
745
      *ptr = '\0';
 
746
      ptr += strlen ( end_header2 );
 
747
      newlen = *len - strlen ( text ) - strlen ( end_header2 );
 
748
      ret = (char *) malloc ( newlen );
 
749
      memcpy ( ret, ptr, newlen );
 
750
      *len = newlen;
 
751
      return ( ret );
 
752
    }
 
753
  }
 
754
 
 
755
  return ( NULL );
 
756
}
 
757
 
 
758
 
 
759
 
 
760
 
 
761
static char *my_strtok ( ptr1, tok )
 
762
char *ptr1;
 
763
char *tok;
 
764
{
 
765
  static char *last;
 
766
  char *p;
 
767
 
 
768
  if ( ! ptr1 )
 
769
    ptr1 = last;
 
770
  else
 
771
    last = ptr1;
 
772
 
 
773
  if ( ! ptr1 )
 
774
    return ( NULL );
 
775
 
 
776
  for ( p = ptr1; *p != '\0'; p++ ) {
 
777
    if ( strncmp ( p, tok, strlen ( tok ) ) == 0 ) {
 
778
      *p = '\0';
 
779
      last = p + strlen ( tok );
 
780
      return ( ptr1 );
 
781
    }
 
782
  }
 
783
 
 
784
  last = NULL;
 
785
  return ( ptr1 );
 
786
}
 
787