1 /****************************************************************/
2 /* Web unit */
3 /* (c) Christophe CALMEJANE (Ze KiLleR) - 1999-06 */
4 /****************************************************************/
5
6 /*
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22
23 /* TO DO :
24 * Purger les cookies expirés
25 */
26
27 #include "skyutils.h"
28
29 #ifndef SU_TRACE_INTERNAL
30 #undef malloc
31 #undef calloc
32 #undef realloc
33 #undef strdup
34 #undef free
35 #endif /* !SU_TRACE_INTERNAL */
36
37 #define SW_DEFAULT_USER_AGENT "Mozilla/6.0 (compatible; MSIE 5.01; Windows NT)"
38 #define SW_DEFAULT_HEADER "Connection: Keep-Alive" "\x0D" "\x0A" "Accept-Language: fr-FR, en" "\x0D" "\x0A" "Accept-Charset: iso-8859-1,*,utf-8" "\x0D" "\x0A" "Accept: text/html, text/plain, text/*, image/gif, image/jpg, image/png, */*" "\x0D" "\x0A"
39 #define DEFAULT_PORT 80
40 #define DEFAULT_SSL_PORT 443
41 #define SOCKET_TIME_OUT 60
42
43 #ifdef __unix__
44 extern int SU_DebugLevel;
45 #endif /* __unix__ */
46
47 char *SW_GetInput_String;
48 char *SW_GetImage_String;
49 char *SW_Proxy_String = NULL;
50 char *SW_Proxy_User = NULL;
51 char *SW_Proxy_Password = NULL;
52 char *SW_UserHeader = NULL;
53 char *SW_UserAgent = NULL;
54 int SW_Proxy_Port = 0;
55 int SW_SocketTimeout = SOCKET_TIME_OUT;
56 SU_PList SW_Cookies = NULL; /* SU_PCookie */
57
58 int SU_Dump_PageNum = 0;
59
DumpPage(const char fname[],const char * buf,const int size)60 void DumpPage(const char fname[],const char *buf,const int size)
61 {
62 FILE *fp;
63 char FN[50];
64
65 if(fname == NULL)
66 {
67 SU_snprintf(FN,sizeof(FN),"Dump%d.html",SU_Dump_PageNum++);
68 printf("SkyUtils_DumpPage : Dumping to %s\n",FN);
69 fp = fopen(FN,"wt");
70 }
71 else
72 fp = fopen(fname,"wb");
73 if(fp == NULL)
74 return;
75 #ifdef __unix__
76 /* this debug view is useful if u need debug dynamic input name and need to know
77 * what page is taken from server */
78 if(SU_DebugLevel >= 10)
79 fwrite(buf,size,1,stdout);
80 #endif /* __unix__ */
81 fwrite(buf,size,1,fp);
82 fclose(fp);
83 }
84
85 /* ** SSL CODE ** */
86 #ifdef SU_USE_SSL
87 #include <openssl/crypto.h>
88 #include <openssl/x509.h>
89 #include <openssl/pem.h>
90 #include <openssl/ssl.h>
91 #include <openssl/err.h>
92 #include <openssl/rand.h>
93 #define SSL_RETRY_LIMIT 20
94 static SSL_CTX *SU_SSL_ctx = NULL;
95
SU_SSL_Init()96 void SU_SSL_Init()
97 {
98 unsigned char Seed[1024];
99 SU_u32 i,j,pid;
100 SSL_load_error_strings();
101 SSL_library_init();
102
103 #ifdef _WIN32
104 pid = (SU_u32) GetTickCount() ^ (SU_u32) time(NULL);
105 #else
106 pid = (((SU_u32) getpid()) << 16) ^ (SU_u32) time(NULL);
107 #endif
108
109 for(i=0;i<sizeof(Seed);i++)
110 {
111 for(j=0,Seed[i]=0;j<8;j++)
112 {
113 Seed[i] |= (pid & 1) << j;
114 pid = ((((pid >> 7) ^ (pid >> 6) ^ (pid >> 2) ^ (pid >> 0)) & 1) << 31) | (pid >> 1);
115 }
116 }
117
118 RAND_seed(Seed,sizeof(Seed));
119 }
120
SU_SSL_InitializeCTX(char * pcError)121 SSL_CTX *SU_SSL_InitializeCTX(char *pcError)
122 {
123 char errormsg[1024];
124 SSL_CTX *sslctx;
125
126 #ifndef OPENSSL_NO_SSL3
127 sslctx = SSL_CTX_new(SSLv3_client_method());
128 #else
129 sslctx = SSL_CTX_new(SSLv23_client_method());
130 #endif
131 if(sslctx == NULL)
132 {
133 ERR_error_string(ERR_get_error(), errormsg);
134 SU_snprintf(pcError, 1024, "SSL_CTX_new(): %s", errormsg);
135 return NULL;
136 }
137
138 SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, NULL);
139
140 return sslctx;
141 }
142
SU_SSL_Create(SU_SOCKET Sock,char * pcError)143 SSL *SU_SSL_Create(SU_SOCKET Sock,char *pcError)
144 {
145 char errormsg[1024];
146 int iError;
147 SSL *ssl;
148
149 if(!SU_SSL_ctx)
150 {
151 SU_SSL_Init();
152 SU_SSL_ctx = SU_SSL_InitializeCTX(pcError);
153 if(SU_SSL_ctx == NULL)
154 return NULL;
155 SSL_CTX_set_options(SU_SSL_ctx, SSL_OP_ALL);
156 SSL_CTX_set_default_verify_paths(SU_SSL_ctx);
157 }
158
159 ssl = SSL_new(SU_SSL_ctx);
160 if(ssl == NULL)
161 {
162 ERR_error_string(ERR_get_error(),errormsg);
163 SU_snprintf(pcError, 1024, "SSL_new(): %s", errormsg);
164 return NULL;
165 }
166
167 iError = SSL_set_fd(ssl,Sock);
168 if(iError == 0)
169 {
170 ERR_error_string(ERR_get_error(), errormsg);
171 SU_snprintf(pcError, 1024, "SSL_connect(): %s", errormsg);
172 SSL_free(ssl);
173 return NULL;
174 }
175 return ssl;
176 }
177
SU_SSL_Connect(SU_SOCKET Sock,char * pcError)178 SSL *SU_SSL_Connect(SU_SOCKET Sock,char *pcError)
179 {
180 int iError;
181 char errormsg[1024];
182
183 SSL *ssl = SU_SSL_Create(Sock,pcError);
184 if(ssl == NULL)
185 return NULL;
186
187 iError = SSL_connect(ssl);
188 if(iError <= 0)
189 {
190 ERR_error_string(ERR_get_error(), errormsg);
191 SU_snprintf(pcError, 1024, "SSL_connect(): %s", errormsg);
192 SSL_free(ssl);
193 return NULL;
194 }
195
196 return ssl;
197 }
198
SU_SSL_Write(SSL * ssl,char * pcData,int iLength,char * pcError)199 int SU_SSL_Write(SSL *ssl, char *pcData, int iLength, char *pcError)
200 {
201 char errormsg[1024];
202 int iNSent;
203 int iOffset;
204 int iToSend;
205 int iWRetries;
206
207 iToSend = iLength;
208 iOffset = iWRetries = 0;
209 do
210 {
211 iNSent = SSL_write(ssl, &pcData[iOffset], iToSend);
212
213 switch (SSL_get_error(ssl, iNSent))
214 {
215 case SSL_ERROR_NONE:
216 iToSend -= iNSent;
217 iOffset += iNSent;
218 break;
219
220 case SSL_ERROR_SSL:
221 if(pcError)
222 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_SSL");
223 return -1;
224 break;
225
226 case SSL_ERROR_WANT_READ:
227 if(pcError)
228 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_WANT_READ");
229 return -1;
230 break;
231
232 case SSL_ERROR_WANT_WRITE:
233 if (++iWRetries >= SSL_RETRY_LIMIT)
234 {
235 if(pcError)
236 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_WANT_WRITE: Retry limit reached!");
237 return -1;
238 }
239 break;
240
241 case SSL_ERROR_WANT_X509_LOOKUP:
242 if(pcError)
243 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_WANT_X509_LOOKUP");
244 return -1;
245 break;
246
247 case SSL_ERROR_SYSCALL:
248 if (ERR_peek_error())
249 {
250 ERR_error_string(ERR_get_error(), errormsg);
251 }
252 if (iNSent == -1)
253 {
254 if(pcError)
255 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_SYSCALL: Underlying I/O error: %s",strerror(errno));
256 }
257 else
258 {
259 if(pcError)
260 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_SYSCALL: Unexpected EOF.");
261 }
262 return -1;
263 break;
264
265 case SSL_ERROR_ZERO_RETURN:
266 if(pcError)
267 SU_snprintf(pcError, 1024, "SSL_write(): SSL_ERROR_ZERO_RETURN: The SSL connection has been closed.");
268 return -1;
269 break;
270
271 default:
272 if(pcError)
273 SU_snprintf(pcError, 1024, "SSL_write(): Undefined error.");
274 return -1;
275 break;
276 }
277 } while (iToSend > 0);
278
279 return iOffset;
280 }
281
SU_SSL_Read(SSL * ssl,char * pcData,int iLength,char * pcError)282 int SU_SSL_Read(SSL *ssl, char *pcData, int iLength, char *pcError)
283 {
284 char errormsg[1024];
285 int iDone;
286 int iNRead;
287 int iRRetries;
288
289 iDone = iRRetries = 0;
290 iNRead = SSL_read(ssl, pcData, iLength);
291 while (iDone == 0)
292 {
293 iDone = 1;
294 switch (SSL_get_error(ssl, iNRead))
295 {
296 case SSL_ERROR_NONE:
297 return iNRead;
298 break;
299
300 case SSL_ERROR_SSL:
301 ERR_error_string(ERR_get_error(), errormsg);
302 if(pcError)
303 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_SSL: %s",errormsg);
304 return -1;
305 break;
306
307 case SSL_ERROR_WANT_READ:
308 if (++iRRetries < SSL_RETRY_LIMIT)
309 {
310 if(pcError)
311 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_WANT_READ");
312 iNRead = SSL_read(ssl, pcData, iLength);
313 iDone = 0;
314 }
315 else
316 {
317 if(pcError)
318 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_WANT_READ: Retry limit reached!");
319 return -1;
320 }
321 break;
322
323 case SSL_ERROR_WANT_WRITE:
324 if(pcError)
325 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_WANT_WRITE");
326 return -1;
327 break;
328
329 case SSL_ERROR_WANT_X509_LOOKUP:
330 if(pcError)
331 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_WANT_X509_LOOKUP");
332 return -1;
333 break;
334
335 case SSL_ERROR_SYSCALL:
336 if (ERR_peek_error())
337 {
338 ERR_error_string(ERR_get_error(), errormsg);
339 }
340 if (iNRead == -1)
341 {
342 if(pcError)
343 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_SYSCALL: Underlying I/O error: %s", strerror(errno));
344 return -1;
345 }
346 else
347 {
348 if(pcError)
349 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_SYSCALL: Unexpected EOF. (%d)",iNRead);
350 return -1;
351 }
352 break;
353
354 case SSL_ERROR_ZERO_RETURN:
355 if(pcError)
356 SU_snprintf(pcError, 1024, "SSL_read(): SSL_ERROR_ZERO_RETURN: The SSL connection has been closed.");
357 return 0;
358 break;
359
360 default:
361 if(pcError)
362 SU_snprintf(pcError, 1024, "SSL_read(): Undefined error.");
363 return -1;
364 break;
365 }
366 }
367 return -1;
368 }
369
SU_SSL_SessionCleanup(SSL * ssl)370 void SU_SSL_SessionCleanup(SSL *ssl)
371 {
372 if(ssl != NULL)
373 {
374 SSL_shutdown(ssl);
375 SSL_free(ssl);
376 }
377 }
378 /* ** END OF SSL CODE ** */
379 #else /* !SU_USE_SSL */
380 typedef void SSL;
381 #endif /* SU_USE_SSL */
382
SU_SetSocketTimeout(const int Timeout)383 void SU_SetSocketTimeout(const int Timeout)
384 {
385 if(Timeout == 0)
386 SW_SocketTimeout = SOCKET_TIME_OUT;
387 else
388 SW_SocketTimeout = Timeout;
389 }
390
SU_SetProxy(const char Proxy[],const int Port,const char User[],const char Password[])391 void SU_SetProxy(const char Proxy[],const int Port,const char User[], const char Password[])
392 {
393 if(SW_Proxy_String != NULL)
394 free(SW_Proxy_String);
395 if((Proxy != NULL)&&(strlen(Proxy)>0))
396 SW_Proxy_String = SU_strdup(Proxy);
397 else
398 SW_Proxy_String = NULL;
399 SW_Proxy_Port = Port;
400 if(SW_Proxy_User != NULL)
401 free(SW_Proxy_User);
402 if((User != NULL)&&(strlen(User)>0))
403 SW_Proxy_User = SU_strdup(User);
404 else
405 SW_Proxy_User = NULL;
406 if(SW_Proxy_Password != NULL)
407 free(SW_Proxy_Password);
408 if((Password != NULL)&&(strlen(Password)>0))
409 SW_Proxy_Password = SU_strdup(Password);
410 else
411 SW_Proxy_Password = NULL;
412 }
413
ExtractPath(char * URL,bool proxy)414 char *ExtractPath(char *URL,bool proxy)
415 {
416 char *path;
417 char l[]=".?/",c;
418 int i;
419
420 if(proxy)
421 {
422 URL = strstr(URL,"://") + 3;
423 URL = strchr(URL,'/');
424 if(URL == NULL)
425 {
426 return SU_strdup("/");
427 }
428 }
429 path = SU_strdup(URL);
430 if(strcmp(path,"/") == 0)
431 return path;
432 if(path[strlen(path)-1] == '/')
433 {
434 path[strlen(path)-1] = 0;
435 return path;
436 }
437 if(SU_strrchrl(path,l,&c) == NULL)
438 return path;
439 if(c == '/')
440 return path;
441
442 i = strlen(path)-1;
443 while(path[i] != '/')
444 {
445 if(i == 0)
446 {
447 path[0] = '/';
448 break;
449 }
450 i--;
451 }
452 if(i == 0)
453 path[1] = 0;
454 else
455 path[i] = 0;
456 return path;
457 }
458
AfficheCookie(SU_PCookie Cok)459 void AfficheCookie(SU_PCookie Cok)
460 {
461 printf("Cookie : %s=%s--\n",Cok->Name,Cok->Value);
462 if(Cok->Domain != NULL)
463 printf(" Domain = %s--\n",Cok->Domain);
464 if(Cok->Path != NULL)
465 printf(" Path = %s--\n",Cok->Path);
466 if(Cok->Expire != NULL)
467 printf(" Expires = %s--\n",Cok->Expire);
468 if(Cok->Secured)
469 printf(" Secured\n");
470 }
471
SU_FreeCookie(SU_PCookie Cok)472 void SU_FreeCookie(SU_PCookie Cok)
473 {
474 free(Cok->Name);
475 free(Cok->Value);
476 if(Cok->Domain != NULL)
477 free(Cok->Domain);
478 if(Cok->Path != NULL)
479 free(Cok->Path);
480 if(Cok->Expire != NULL)
481 free(Cok->Expire);
482 free(Cok);
483 }
484
GetPortFromHost(char * Host,bool ssl_mode)485 int GetPortFromHost(char *Host,bool ssl_mode)
486 {
487 char *p;
488
489 p = strchr(Host,':');
490 if(p == NULL)
491 {
492 return ssl_mode?DEFAULT_SSL_PORT:DEFAULT_PORT;
493 }
494 p[0] = 0;
495 p++;
496 return atoi(p);
497 }
498
GetHostFromURL(const char * URL,char Host[],int Length,bool proxy,char URL_OUT[],int * PortConnect,const char OtherHost[],bool * ssl_mode)499 int GetHostFromURL(const char *URL,char Host[],int Length,bool proxy,char URL_OUT[],int *PortConnect,const char OtherHost[],bool *ssl_mode)
500 {
501 char *ptr,*ptr2;
502 int len;
503 char buf[URL_BUF_SIZE];
504 char ReplaceHost[URL_BUF_SIZE];
505
506 SU_strcpy(ReplaceHost,OtherHost,sizeof(ReplaceHost));
507 SU_strcpy(URL_OUT,URL,URL_BUF_SIZE);
508 *ssl_mode = false;
509 if(SU_nocasestrstr((char *)URL,"https") == URL)
510 {
511 #ifndef SU_USE_SSL
512 printf("SkyUtils_GetHostFromURL Error : HTTPS requested, but skyutils was not compiled with SSL support. Exiting !\n");
513 return -10;
514 *ssl_mode = false;
515 #else /* SU_USE_SSL */
516 *ssl_mode = true;
517 #endif /* ! SU_USE_SSL */
518 ptr = (char *)URL+8;
519 ptr2 = strchr(ptr,'/');
520 }
521 else if(SU_nocasestrstr((char *)URL,"http") == URL)
522 {
523 ptr = (char *)URL+7;
524 ptr2 = strchr(ptr,'/');
525 }
526 else if(SU_nocasestrstr((char *)URL,"ftp") == URL)
527 {
528 ptr = (char *)URL+6;
529 ptr2 = strchr(ptr,'@');
530 if(ptr2 != NULL)
531 {
532 ptr = ptr2+1;
533 ptr2 = strchr(ptr,'/');
534 }
535 }
536 else
537 {
538 if(ReplaceHost[0] == 0)
539 SU_strcpy(Host,URL,Length);
540 else
541 SU_strcpy(Host,ReplaceHost,Length);
542 if(!proxy)
543 {
544 URL_OUT[0] = '/';
545 URL_OUT[1] = 0;
546 *PortConnect = GetPortFromHost(Host,*ssl_mode);
547 }
548 return 0;
549 }
550 if(ptr2 == NULL)
551 {
552 if(ReplaceHost[0] == 0)
553 SU_strcpy(Host,ptr,Length);
554 else
555 SU_strcpy(Host,ReplaceHost,Length);
556 if(!proxy)
557 {
558 URL_OUT[0] = '/';
559 URL_OUT[1] = 0;
560 *PortConnect = GetPortFromHost(Host,*ssl_mode);
561 }
562 return 0;
563 }
564 len = ptr2 - ptr + 1; /* +1 for the \0 */
565 if(len > Length)
566 len = Length;
567 if(ReplaceHost[0] == 0)
568 {
569 SU_strcpy(Host,ptr,len);
570 }
571 else
572 {
573 SU_strcpy(Host,ReplaceHost,Length);
574 }
575 if(!proxy)
576 { /* If not using a proxy, we must remove host from URL_OUT */
577 SU_strcpy(buf,ptr2,sizeof(buf));
578 SU_strcpy(URL_OUT,buf,URL_BUF_SIZE);
579 *PortConnect = GetPortFromHost(Host,*ssl_mode);
580 }
581 else
582 { /* Using proxy ? */
583 if(ReplaceHost[0] != 0)
584 { /* Ahh, we must replace host in URL_OUT */
585 if(URL[0] == 'h')
586 {
587 if(*ssl_mode)
588 strcpy(URL_OUT,"https://");
589 else
590 strcpy(URL_OUT,"http://");
591 }
592 else
593 strcpy(URL_OUT,"ftp://");
594 SU_strcpy(buf,ptr2,sizeof(buf));
595 SU_strcat(URL_OUT,ReplaceHost,URL_BUF_SIZE);
596 SU_strcat(URL_OUT,buf,URL_BUF_SIZE);
597 *PortConnect = GetPortFromHost((char *)ReplaceHost,*ssl_mode);
598 }
599 }
600 return 0;
601 }
602
FreeAnswer(SU_PAnswer Ans)603 void FreeAnswer(SU_PAnswer Ans)
604 {
605 if(Ans == NULL)
606 return;
607 if(Ans->Location != NULL)
608 free(Ans->Location);
609 if(Ans->Data != NULL)
610 free(Ans->Data);
611 }
612
ParseBuffer(SU_PAnswer Ans,char * Buf,int * len,SU_PHTTPActions Act,bool proxy)613 SU_PAnswer ParseBuffer(SU_PAnswer Ans,char *Buf,int *len,SU_PHTTPActions Act,bool proxy)
614 {
615 char *ptr,*ptr2;
616 char *tmp,*tok;
617 char *saf; /* Used at the end of the while ! DO NOT USE */
618 SU_PCookie Cok;
619 float f;
620 SU_PList Ptr;
621
622 if(Ans == NULL)
623 {
624 Ans = (SU_PAnswer) malloc(sizeof(SU_TAnswer));
625 memset(Ans,0,sizeof(SU_TAnswer));
626 Ans->Data_Length = -1;
627 Ans->Data_ToReceive = -1;
628 }
629 if(Ans->Data_Length != -1)
630 {
631 Ans->Data = (char *) realloc(Ans->Data,Ans->Data_Length+*len+1); /* +1 for \0 */
632 memcpy(Ans->Data+Ans->Data_Length,Buf,*len);
633 Ans->Data_Length += *len;
634 Ans->Data[Ans->Data_Length] = 0;
635 *len = 0;
636 return Ans;
637 }
638 while(*len != 0)
639 {
640 ptr = strstr(Buf,"\r\n");
641 if(ptr == NULL) /* Not enough bytes received */
642 return Ans;
643 if(ptr == Buf) /* Data following */
644 {
645 #ifdef __unix__
646 if(SU_DebugLevel >= 3)
647 {
648 printf("SkyUtils_ParseBuffer : Found Data in HTTP answer\n");
649 if(Ans->Data_ToReceive >= 0)
650 printf("SkyUtils_ParseBuffer : Waiting %d bytes\n",Ans->Data_ToReceive);
651 }
652 #endif /* __unix__ */
653 Ans->Data_Length = 0;
654 if(*len == 2) /* Not enough data */
655 return Ans;
656 Ans->Data = (char *) malloc(*len-2+1); /* +1 for \0 */
657 memcpy(Ans->Data,Buf+2,*len-2);
658 Ans->Data_Length = *len - 2;
659 Ans->Data[Ans->Data_Length] = 0;
660 *len = 0;
661 return Ans;
662 }
663 ptr[0] = 0;
664 saf = ptr;
665 /* Parse header command */
666 #ifdef __unix__
667 if(SU_DebugLevel >= 3)
668 printf("SkyUtils_ParseBuffer : Found header : %s\n",Buf);
669 #endif /* __unix__ */
670 if(SU_nocasestrstr(Buf,"HTTP/") == Buf) /* Found reply code */
671 {
672 sscanf(Buf,"HTTP/%f %d",&f,&Ans->Code);
673 }
674 else if(SU_nocasestrstr(Buf,"Content-Length") == Buf)
675 {
676 Ans->Data_ToReceive = atoi(strchr(Buf,':')+1);
677 }
678 else if(SU_nocasestrstr(Buf,"Set-Cookie") == Buf) /* Found Set-Cookie */
679 {
680 Cok = (SU_PCookie) malloc(sizeof(SU_TCookie));
681 memset(Cok,0,sizeof(SU_TCookie));
682 tmp = SU_TrimLeft(strchr(Buf,':') + 1);
683 tmp = SU_strdup(tmp);
684 tok = SU_TrimLeft(strtok(tmp,";"));
685 /* Get NAME=VALUE */
686 ptr2 = strchr(tok,'=');
687 ptr2[0] = 0;
688 Cok->Name = SU_strdup(tok);
689 Cok->Value = SU_strdup(ptr2+1);
690 /* Get options */
691 tok = SU_TrimLeft(strtok(NULL,";"));
692 while(tok != NULL)
693 {
694 if(strncasecmp(tok,"expires",7) == 0)
695 {
696 ptr2 = strchr(tok,'=');
697 if(ptr2 != NULL)
698 {
699 Cok->Expire = SU_strdup(ptr2+1);
700 }
701 else
702 printf("SkyUtils_ParseBuffer Warning : Error with Expire value in cookie : %s\n",tok);
703 }
704 else if(strncasecmp(tok,"path",4) == 0)
705 {
706 ptr2 = strchr(tok,'=');
707 if(ptr2 != NULL)
708 {
709 Cok->Path = SU_strdup(ptr2+1);
710 }
711 else
712 printf("SkyUtils_ParseBuffer Warning : Error with Path value in cookie : %s\n",tok);
713 }
714 else if(strncasecmp(tok,"domain",6) == 0)
715 {
716 ptr2 = strchr(tok,'=');
717 if(ptr2 != NULL)
718 {
719 if(ptr2[1] == '.')
720 Cok->Domain = SU_strdup(ptr2+2);
721 else
722 Cok->Domain = SU_strdup(ptr2+1);
723 }
724 else
725 printf("SkyUtils_ParseBuffer Warning : Error with Domain value in cookie : %s\n",tok);
726 }
727 else if(strncasecmp(tok,"secure",6) == 0)
728 {
729 Cok->Secured = true;
730 }
731 #ifdef __unix__
732 else if(SU_DebugLevel >= 1)
733 printf("SkyUtils_ParseBuffer Warning : Unknown option in Set-Cookie : %s\n",tok);
734 #endif /* __unix__ */
735 tok = SU_TrimLeft(strtok(NULL,";"));
736 }
737 free(tmp);
738 if(Cok->Domain == NULL)
739 {
740 Cok->Domain = SU_strdup(Act->Host);
741 }
742 if(Cok->Path == NULL)
743 {
744 tmp = ExtractPath(Act->URL,proxy);
745 Cok->Path = SU_strdup(tmp);
746 free(tmp);
747 }
748 #ifdef __unix__
749 if(SU_DebugLevel >= 4)
750 AfficheCookie(Cok);
751 #endif /* __unix__ */
752 /* Check if a cookie with same Name/Domain/Path exists */
753 Ptr = SW_Cookies;
754 while(Ptr != NULL)
755 {
756 if((strcmp(((SU_PCookie)Ptr->Data)->Name,Cok->Name) == 0) && (strcmp(((SU_PCookie)Ptr->Data)->Domain,Cok->Domain) == 0))
757 {
758 if((Cok->Path != NULL) && (((SU_PCookie)Ptr->Data)->Path != NULL))
759 {
760 if(strcmp(((SU_PCookie)Ptr->Data)->Path,Cok->Path) == 0)
761 {
762 SU_FreeCookie((SU_PCookie)Ptr->Data);
763 Ptr->Data = Cok;
764 break;
765 }
766 }
767 }
768 Ptr = Ptr->Next;
769 }
770 if(Ptr == NULL)
771 SW_Cookies = SU_AddElementTail(SW_Cookies,Cok);
772 }
773 else if(SU_nocasestrstr(Buf,"Location") == Buf) /* Found Location */
774 {
775 ptr2 = SU_TrimLeft(strchr(Buf,':') + 1);
776 Ans->Location = SU_strdup(ptr2);
777 }
778 /* End of parse header command */
779 *len -= (saf - Buf) + 2;
780 memmove(Buf,saf+2,*len);
781 }
782 return Ans;
783 }
784
CreateConnection(char Host[],int Port,SSL ** ssl)785 int CreateConnection(char Host[],int Port,SSL **ssl)
786 {
787 SU_SOCKET Sock;
788 struct sockaddr_in sin;
789 struct hostent *HE;
790
791 Sock = socket(AF_INET,SOCK_STREAM,getprotobyname("tcp")->p_proto);
792 if(Sock == -1)
793 return -1;
794 sin.sin_family = AF_INET;
795 sin.sin_port = htons(Port);
796 sin.sin_addr.s_addr = inet_addr(Host);
797 if(sin.sin_addr.s_addr == INADDR_NONE)
798 {
799 HE = gethostbyname(Host);
800 if( HE == NULL )
801 {
802 printf("SkyUtils_CreateConnection : Unknown Host : %s\n",Host);
803 return -2;
804 }
805 sin.sin_addr = *(struct in_addr *)(HE->h_addr_list[0]);
806 }
807 if(connect(Sock,(struct sockaddr *)(&sin),sizeof(sin)) == -1)
808 {
809 SU_CLOSE_SOCKET(Sock);
810 return -3;
811 }
812 #ifdef SU_USE_SSL
813 if(ssl != NULL)
814 {
815 char errormsg[1024];
816 *ssl = SU_SSL_Connect(Sock,errormsg);
817 if(*ssl == NULL)
818 {
819 printf("SkyUtils_CreateConnection : %s\n", errormsg);
820 SU_CLOSE_SOCKET(Sock);
821 return -4;
822 }
823 }
824 #endif
825 return Sock;
826 }
827
828 /* Base64 encode a string */
http_base64_encode(const char * text)829 char * http_base64_encode(const char *text)
830 {
831
832 const char b64_alphabet[65] = {
833 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
834 "abcdefghijklmnopqrstuvwxyz"
835 "0123456789+/=" };
836
837 /* The tricky thing about this is doing the padding at the end,
838 * doing the bit manipulation requires a bit of concentration only */
839 char *buffer = NULL;
840 char *point = NULL;
841 int inlen = 0;
842 int outlen = 0;
843
844 /* check our args */
845 if (text == NULL)
846 return NULL;
847
848 /* Use 'buffer' to store the output. Work out how big it should be...
849 * This must be a multiple of 4 bytes */
850
851 inlen = strlen( text );
852 /* check our arg...avoid a pesky FPE */
853 if (inlen == 0)
854 {
855 buffer = (char *) malloc(sizeof(char));
856 buffer[0] = '\0';
857 return buffer;
858 }
859 outlen = (inlen*4)/3;
860 if( (inlen % 3) > 0 ) /* got to pad */
861 outlen += 4 - (inlen % 3);
862
863 buffer = (char *) malloc( outlen + 1 ); /* +1 for the \0 */
864 memset(buffer, 0, outlen + 1); /* initialize to zero */
865
866 /* now do the main stage of conversion, 3 bytes at a time,
867 * leave the trailing bytes (if there are any) for later */
868
869 for( point=buffer; inlen>=3; inlen-=3, text+=3 ) {
870 *(point++) = b64_alphabet[ *text>>2 ];
871 *(point++) = b64_alphabet[ (*text<<4 & 0x30) | *(text+1)>>4 ];
872 *(point++) = b64_alphabet[ (*(text+1)<<2 & 0x3c) | *(text+2)>>6 ];
873 *(point++) = b64_alphabet[ *(text+2) & 0x3f ];
874 }
875
876 /* Now deal with the trailing bytes */
877 if( inlen ) {
878 /* We always have one trailing byte */
879 *(point++) = b64_alphabet[ *text>>2 ];
880 *(point++) = b64_alphabet[ (*text<<4 & 0x30) |
881 (inlen==2?*(text+1)>>4:0) ];
882 *(point++) = (inlen==1?'=':b64_alphabet[ *(text+1)<<2 & 0x3c ] );
883 *(point++) = '=';
884 }
885
886 *point = '\0';
887
888 return buffer;
889 }
890
SendBuffer(int Sock,char * buf,int len,SSL * ssl,bool verbose)891 static int SendBuffer(int Sock,char *buf,int len,SSL *ssl,bool verbose)
892 {
893 int res;
894
895 #ifdef SU_USE_SSL
896 if(ssl)
897 {
898 if(verbose)
899 {
900 char errormsg[1024];
901 res = SU_SSL_Write(ssl,buf,len,errormsg);
902 if(res == -1)
903 {
904 printf("SkyUtils_SendCommand Error : Error sending command using SSL : %s\n",errormsg);
905 }
906 }
907 else
908 res = SU_SSL_Write(ssl,buf,len,NULL);
909 }
910 else
911 #endif /* SU_USE_SSL */
912 #ifdef __unix__
913 if(SU_DebugLevel >= 2)
914 printf("SkyUtils_SendCommand : Sending %s(%d) : %s\n",ssl?"SSL ":"",len,buf);
915 #endif /* __unix__ */
916 res = send(Sock,buf,len,0);
917 return res;
918 }
919
SendFile(int Sock,FILE * fp,int FLen,SSL * ssl)920 static int SendFile(int Sock,FILE *fp,int FLen,SSL *ssl)
921 {
922 int res = 0;
923 char buf[16000];
924 int len,pos;
925
926 while(res >= 0)
927 {
928 len = (FLen > sizeof(buf))?sizeof(buf):FLen;
929 if(fread(buf,len,1,fp) != 1)
930 {
931 res = -1;
932 break;
933 }
934 #ifdef SU_USE_SSL
935 if(ssl)
936 res = SU_SSL_Write(ssl,buf,len,NULL);
937 else
938 #endif /* SU_USE_SSL */
939 res = send(Sock,buf,len,SU_MSG_NOSIGNAL);
940 FLen -= len;
941 if(res <= 0)
942 {
943 res = -1;
944 break;
945 }
946 else if(res != len)
947 { /* Not all bytes sent */
948 pos = res;
949 len -= res;
950 while(len > 0)
951 {
952 #ifdef SU_USE_SSL
953 if(ssl)
954 res = SU_SSL_Write(ssl,buf+pos,len,NULL);
955 else
956 #endif /* SU_USE_SSL */
957 res = send(Sock,buf+pos,len,SU_MSG_NOSIGNAL);
958 if(res <= 0)
959 break;
960 pos += res;
961 len -= res;
962 }
963 if(res <= 0)
964 break;
965 }
966 if(FLen == 0)
967 {
968 len = 0;
969 buf[len++] = 0x0D;
970 buf[len++] = 0x0A;
971 buf[len] = 0;
972 #ifdef SU_USE_SSL
973 if(ssl)
974 res = SU_SSL_Write(ssl,buf,len,NULL);
975 else
976 #endif /* SU_USE_SSL */
977 send(Sock,buf,len,SU_MSG_NOSIGNAL);
978 #ifdef __unix__
979 if(SU_DebugLevel >= 2)
980 printf("SkyUtils_SendCommand : Successfully sent file\n");
981 #endif /* __unix__ */
982 res = 0;
983 break;
984 }
985 }
986 return res;
987 }
988
SendCommand(SU_SOCKET Sock,SU_PHTTPActions Act,bool proxy,SSL * ssl)989 bool SendCommand(SU_SOCKET Sock,SU_PHTTPActions Act,bool proxy,SSL *ssl)
990 {
991 char buf[16000];
992 int len;
993 SU_u64 FLen;
994 int res;
995 char *Com,*tmp,*tmp2,*tmp3;
996 SU_PList Ptr;
997 int cook,blen,blen2;
998 FILE *fp;
999 bool do_it;
1000
1001 if(Act->Command == ACT_GET)
1002 Com = "GET";
1003 else if(Act->Command == ACT_POST)
1004 Com = "POST";
1005 else if(Act->Command == ACT_PUT)
1006 Com = "PUT";
1007 else if(Act->Command == ACT_DELETE)
1008 Com = "DELETE";
1009 else
1010 Com = "ERROR";
1011 if(Act->URL_Params == NULL)
1012 SU_snprintf(buf,sizeof(buf),"%s %s HTTP/1.0%c%cHost: %s%c%c",Com,Act->URL,0x0D,0x0A,Act->Host,0x0D,0x0A);
1013 else
1014 SU_snprintf(buf,sizeof(buf),"%s %s?%s HTTP/1.0%c%cHost: %s%c%c",Com,Act->URL,Act->URL_Params,0x0D,0x0A,Act->Host,0x0D,0x0A);
1015 len = strlen(buf);
1016 /* Now add header from file, or default one */
1017 if(SW_UserHeader == NULL)
1018 {
1019 if(SW_UserAgent == NULL)
1020 SU_SetUserAgent(SW_DEFAULT_USER_AGENT);
1021 SU_snprintf(buf+len,sizeof(buf)-len,"User-Agent: %s\x0D\x0A%s",SW_UserAgent,SW_DEFAULT_HEADER);
1022 }
1023 else
1024 SU_snprintf(buf+len,sizeof(buf)-len,"%s",SW_UserHeader);
1025 len = strlen(buf);
1026
1027 Ptr = SW_Cookies;
1028 cook = 0;
1029 while(Ptr != NULL)
1030 {
1031 blen = strlen(((SU_PCookie)Ptr->Data)->Domain)+2;
1032 if(strchr(Act->Host,':') == NULL)
1033 {
1034 tmp = (char *) malloc(blen);
1035 SU_snprintf(tmp,blen,"*%s",((SU_PCookie)Ptr->Data)->Domain);
1036 }
1037 else
1038 {
1039 tmp = (char *) malloc(blen+2);
1040 SU_snprintf(tmp,blen+2,"*%s:*",((SU_PCookie)Ptr->Data)->Domain);
1041 }
1042 if(SU_strwcmp(Act->Host,tmp))
1043 {
1044 do_it = false;
1045 if(((SU_PCookie)Ptr->Data)->Path == NULL)
1046 do_it = true;
1047 else
1048 {
1049 blen2 = strlen(((SU_PCookie)Ptr->Data)->Path)+2;
1050 tmp2 = (char *) malloc(blen2);
1051 SU_snprintf(tmp2,blen2,"%s*",((SU_PCookie)Ptr->Data)->Path);
1052 tmp3 = ExtractPath(Act->URL,proxy);
1053 if(SU_strwcmp(tmp3,tmp2))
1054 do_it = true;
1055 free(tmp2);
1056 free(tmp3);
1057 }
1058 if(do_it)
1059 {
1060 if(cook == 0)
1061 {
1062 SU_snprintf(buf+len,sizeof(buf)-len,"Cookie: %s=%s",((SU_PCookie)Ptr->Data)->Name,((SU_PCookie)Ptr->Data)->Value);
1063 len = strlen(buf);
1064 cook = 1;
1065 }
1066 else
1067 {
1068 SU_snprintf(buf+len,sizeof(buf)-len,"; %s=%s",((SU_PCookie)Ptr->Data)->Name,((SU_PCookie)Ptr->Data)->Value);
1069 len = strlen(buf);
1070 }
1071 }
1072 }
1073 free(tmp);
1074 Ptr = Ptr->Next;
1075 }
1076 if(cook != 0)
1077 {
1078 buf[len++] = 0x0D;
1079 buf[len++] = 0x0A;
1080 }
1081 if(Act->Referer != NULL)
1082 {
1083 SU_snprintf(buf+len,sizeof(buf)-len,"Referer: %s%c%c",Act->Referer,0x0D,0x0A);
1084 len = strlen(buf);
1085 }
1086 /* Manage proxy authorization */
1087 if(proxy != 0)
1088 {
1089 if(SW_Proxy_User != NULL)
1090 {
1091 char authtoken[256];
1092 char *auth64=NULL;
1093
1094 if(SW_Proxy_Password != NULL)
1095 SU_snprintf(authtoken,255,"%s:%s",SW_Proxy_User,SW_Proxy_Password);
1096 else
1097 SU_snprintf(authtoken,255,"%s:",SW_Proxy_User);
1098 auth64 = http_base64_encode(authtoken);
1099 if(auth64 != NULL)
1100 {
1101 SU_snprintf(buf+len,sizeof(buf)-len,"Proxy-Authorization: Basic %s%c%c",auth64,0x0D,0x0A);
1102 len = strlen(buf);
1103 free(auth64);
1104 }
1105 }
1106 }
1107 if(Act->Command == ACT_POST)
1108 {
1109 if(Act->MultiParts == NULL) /* Post_Data */
1110 {
1111 SU_snprintf(buf+len,sizeof(buf)-len,"Content-type: application/x-www-form-urlencoded%c%cContent-length: %d%c%c%c%c",0x0D,0x0A,Act->Post_Length,0x0D,0x0A,0x0D,0x0A);
1112 len = strlen(buf);
1113 memcpy(buf+len,Act->Post_Data,Act->Post_Length);
1114 len += Act->Post_Length;
1115 buf[len++] = 0x0D;
1116 buf[len++] = 0x0A;
1117 buf[len] = 0;
1118 SendBuffer(Sock,buf,len,ssl,true);
1119 }
1120 else /* MultiParts */
1121 {
1122 int multi_length = 0;
1123 SU_PList Ptr = Act->MultiParts;
1124 SU_PHTTPPart Part;
1125 char boundary[27+13+1];
1126 int boundary_length;
1127 SU_u32 tim = (SU_u32) time(NULL);
1128 SU_u32 pid = SU_PROCESS_SELF;
1129 SU_u32 tid = SU_THREAD_SELF;
1130 if(tim >= 0x1000000)
1131 tim &= 0xFFFFFF;
1132 if(pid >= 0x10000)
1133 pid &= 0xFFFF;
1134 if(tid >= 0x1000)
1135 tid &= 0xFFF;
1136
1137 SU_snprintf(boundary,sizeof(boundary),"---------------------------%06x%04x%03x",tim,pid,tid);
1138 boundary_length = strlen(boundary);
1139 while(Ptr != NULL)
1140 {
1141 Part = (SU_PHTTPPart) Ptr->Data;
1142 if(Part->FileName)
1143 {
1144 fp = fopen(Part->FileName,"rb");
1145 if(fp == NULL)
1146 return false;
1147 fseek(fp,0,SEEK_END);
1148 Part->Length = ftell(fp);
1149 fclose(fp);
1150 }
1151 multi_length += Part->Length + boundary_length + 2 + 2 + 2; /* +2 (--) before boundary, +2 (\n) after boundary, +2 (\n) at end of part */
1152 if(Part->Header)
1153 {
1154 multi_length += strlen(Part->Header) + 2; /* +2 after header */
1155 }
1156 multi_length += 2; /* +2 (--) for final boundary */
1157 Ptr = Ptr->Next;
1158 }
1159 SU_snprintf(buf+len,sizeof(buf)-len,"Content-type: multipart/form-data; boundary=%s%c%cContent-length: %d%c%c%c%c",boundary,0x0D,0x0A,multi_length,0x0D,0x0A,0x0D,0x0A);
1160 len = strlen(buf);
1161 buf[len] = 0;
1162 SendBuffer(Sock,buf,len,ssl,true);
1163
1164 Ptr = Act->MultiParts;
1165 while(Ptr != NULL)
1166 {
1167 Part = (SU_PHTTPPart) Ptr->Data;
1168 if(Part->Header)
1169 {
1170 SU_snprintf(buf,sizeof(buf),"--%s%c%c%s%c%c%c%c",boundary,0x0D,0x0A,Part->Header,0x0D,0x0A,0x0D,0x0A);
1171 len = strlen(buf);
1172 buf[len] = 0;
1173 }
1174 else
1175 {
1176 SU_snprintf(buf,sizeof(buf),"--%s%c%c%c%c",boundary,0x0D,0x0A,0x0D,0x0A);
1177 len = strlen(buf);
1178 buf[len] = 0;
1179 }
1180 SendBuffer(Sock,buf,len,ssl,true);
1181 if(Part->FileName) /* File */
1182 {
1183 fp = fopen(Part->FileName,"rb");
1184 if(fp == NULL)
1185 return false;
1186 res = SendFile(Sock,fp,Part->Length,ssl);
1187 fclose(fp);
1188 if(res == -1)
1189 return false;
1190 }
1191 else /* Data */
1192 {
1193 SendBuffer(Sock,Part->Data,Part->Length,ssl,false);
1194 }
1195 /* End of boundary */
1196 SU_snprintf(buf,sizeof(buf),"%c%c",0x0D,0x0A);
1197 len = strlen(buf);
1198 buf[len] = 0;
1199 SendBuffer(Sock,buf,len,ssl,true);
1200 Ptr = Ptr->Next;
1201 }
1202 /* Final boundary */
1203 SU_snprintf(buf,sizeof(buf),"--%s--%c%c",boundary,0x0D,0x0A);
1204 len = strlen(buf);
1205 buf[len] = 0;
1206 SendBuffer(Sock,buf,len,ssl,true);
1207 }
1208 }
1209 else if((Act->Command == ACT_GET) || (Act->Command == ACT_DELETE))
1210 {
1211 if(Act->ContentType != NULL)
1212 {
1213 SU_snprintf(buf+len,sizeof(buf)-len,"Content-Type: %s%c%c",Act->ContentType,0x0D,0x0A);
1214 len = strlen(buf);
1215 }
1216 buf[len++] = 0x0D;
1217 buf[len++] = 0x0A;
1218 buf[len] = 0;
1219 SendBuffer(Sock,buf,len,ssl,true);
1220 }
1221 if(Act->Command == ACT_PUT)
1222 {
1223 fp = fopen(Act->FileName,"rb");
1224 if(fp == NULL)
1225 return false;
1226 fseek(fp,0,SEEK_END);
1227 FLen = (SU_u64)ftell(fp);
1228 rewind(fp);
1229 #ifdef __unix__
1230 if(SU_DebugLevel >= 2)
1231 printf("SkyUtils_SendCommand : Sending file %s of length %ld\n",Act->FileName,FLen);
1232 #endif /* __unix__ */
1233 SU_snprintf(buf+len,sizeof(buf)-len,"Content-Type: application/octet-stream%c%cContent-length: %ld%c%c%c%c",FLen,0x0D,0x0A,0x0D,0x0A,0x0D,0x0A);
1234 len = strlen(buf);
1235 res = SendBuffer(Sock,buf,len,ssl,true);
1236 res = SendFile(Sock,fp,(int)FLen,ssl);
1237 fclose(fp);
1238 if(res == -1)
1239 {
1240 if(Act->CB.OnErrorSendingFile != NULL)
1241 Act->CB.OnErrorSendingFile(errno,Act->User);
1242 #ifdef __unix__
1243 if(SU_DebugLevel >= 2)
1244 printf("SkyUtils_SendCommand Warning : Error sending file, %ld bytes remaining that were not sent\n",FLen);
1245 #endif /* __unix__ */
1246 }
1247 #ifdef SU_USE_SSL
1248 if(ssl)
1249 {
1250 SU_SSL_SessionCleanup(ssl);
1251 }
1252 #endif /* SU_USE_SSL */
1253 SU_CLOSE_SOCKET(Sock);
1254 return res == 0;
1255 }
1256 return true;
1257 }
1258
WaitForAnswer(SU_SOCKET Sock,SU_PHTTPActions Act,bool proxy,SSL * ssl)1259 SU_PAnswer WaitForAnswer(SU_SOCKET Sock,SU_PHTTPActions Act,bool proxy,SSL *ssl)
1260 {
1261 int len;
1262 int BufPos = 0;
1263 char Buf[32768];
1264 SU_PAnswer Ans = NULL;
1265 fd_set rfds;
1266 struct timeval tv;
1267 int retval;
1268
1269 FD_ZERO(&rfds);
1270 FD_SET(Sock,&rfds);
1271 tv.tv_sec = SW_SocketTimeout;
1272 tv.tv_usec = 0;
1273 retval = select(Sock+1,&rfds,NULL,NULL,&tv);
1274 if(retval != 1)
1275 return NULL;
1276 #ifdef SU_USE_SSL
1277 if(ssl)
1278 len = SU_SSL_Read(ssl,Buf,sizeof(Buf),NULL);
1279 else
1280 #endif /* SU_USE_SSL */
1281 len = recv(Sock,Buf,sizeof(Buf),0);
1282 while(len > 0)
1283 {
1284 len += BufPos;
1285 Ans = ParseBuffer(Ans,Buf,&len,Act,proxy);
1286 BufPos = len;
1287 if(Ans->Data_ToReceive >= 0)
1288 {
1289 if(Ans->Data_Length >= Ans->Data_ToReceive)
1290 break;
1291 }
1292 FD_ZERO(&rfds);
1293 FD_SET(Sock,&rfds);
1294 tv.tv_sec = SW_SocketTimeout;
1295 tv.tv_usec = 0;
1296 retval = select(Sock+1,&rfds,NULL,NULL,&tv);
1297 if(retval == 0) /* Time out */
1298 {
1299 if(Ans->Data_Length == -1)
1300 {
1301 FreeAnswer(Ans);
1302 Ans = NULL;
1303 }
1304 #ifdef __unix__
1305 else if(SU_DebugLevel >= 1)
1306 printf("SkyUtils_WaitForAnswer Warning : Connection timed out, but some data was retrieved\n");
1307 // printf("SkyUtils_WaitForAnswer Warning : Connection timed out, but some datas were retrieved\n");
1308 #endif /* __unix__ */
1309 break;
1310 }
1311 else if(retval < 0)
1312 {
1313 if(Ans->Data_Length == -1)
1314 {
1315 FreeAnswer(Ans);
1316 Ans = NULL;
1317 }
1318 #ifdef __unix__
1319 else if(SU_DebugLevel >= 1)
1320 printf("SkyUtils_WaitForAnswer Warning : Unexpected network error : %d\n",errno);
1321 #endif /* __unix__ */
1322 break;
1323 }
1324 #ifdef SU_USE_SSL
1325 if(ssl)
1326 len = SU_SSL_Read(ssl,Buf+BufPos,sizeof(Buf)-BufPos,NULL);
1327 else
1328 #endif /* SU_USE_SSL */
1329 len = recv(Sock,Buf+BufPos,sizeof(Buf)-BufPos,0);
1330 }
1331 #ifdef SU_USE_SSL
1332 if(ssl)
1333 {
1334 SU_SSL_SessionCleanup(ssl);
1335 }
1336 #endif /* SU_USE_SSL */
1337 SU_CLOSE_SOCKET(Sock);
1338 if(Ans != NULL)
1339 {
1340 #ifdef __unix__
1341 if(SU_DebugLevel >= 5)
1342 DumpPage(NULL,Ans->Data,Ans->Data_Length);
1343 #endif /* __unix__ */
1344 if((Ans->Data != NULL) && (Act->FileName != NULL) && ((Act->Command == ACT_GET) || (Act->Command == ACT_POST)))
1345 DumpPage(Act->FileName,Ans->Data,Ans->Data_Length);
1346 }
1347 return Ans;
1348 }
1349
SU_SendProxySSLConnect(SU_SOCKET Sock,char * Host,int Port,int * Code)1350 bool SU_SendProxySSLConnect(SU_SOCKET Sock,char *Host,int Port,int *Code)
1351 {
1352 char buf[1024];
1353 int res,len;
1354 fd_set rfds;
1355 struct timeval tv;
1356 int retval,BufPos = 0;
1357 bool found = false,again = true;
1358 char *ptr;
1359 float f;
1360
1361 if(SW_UserAgent == NULL)
1362 SU_SetUserAgent(SW_DEFAULT_USER_AGENT);
1363 SU_snprintf(buf,sizeof(buf),"CONNECT %s:%d HTTP/1.0%c%cUser-Agent: %s%c%cHost: %s%c%cProxy-Connection: close%c%cConnection: close%c%c%c%c",Host,Port,0x0D,0x0A,SW_UserAgent,0x0D,0x0A,Host,0x0D,0x0A,0x0D,0x0A,0x0D,0x0A,0x0D,0x0A);
1364 len = strlen(buf);
1365 res = send(Sock,buf,len,0);
1366 if(res != len)
1367 return false;
1368
1369 FD_ZERO(&rfds);
1370 FD_SET(Sock,&rfds);
1371 tv.tv_sec = SW_SocketTimeout;
1372 tv.tv_usec = 0;
1373 retval = select(Sock+1,&rfds,NULL,NULL,&tv);
1374 if(retval != 1)
1375 return false;
1376 res = recv(Sock,buf,sizeof(buf)-1,0);
1377 while((res > 0) && again)
1378 {
1379 BufPos += res;
1380 buf[BufPos] = 0;
1381 ptr = strstr(buf,"\r\n");
1382 while(ptr != NULL)
1383 {
1384 if(ptr == buf) /* End of answer */
1385 {
1386 again = false;
1387 break;
1388 }
1389 if(SU_nocasestrstr(buf,"HTTP/") == buf) /* Found reply code */
1390 {
1391 sscanf(buf,"HTTP/%f %d",&f,Code);
1392 if(*Code == 200) /* Ok */
1393 {
1394 BufPos = 0;
1395 found = true;
1396 break;
1397 }
1398 }
1399 BufPos -= ptr+2-buf-1; /* -1 for \0 */
1400 memmove(buf,ptr+2,BufPos);
1401 ptr = strstr(buf,"\r\n");
1402 }
1403 if(again)
1404 break;
1405 FD_ZERO(&rfds);
1406 FD_SET(Sock,&rfds);
1407 tv.tv_sec = SW_SocketTimeout;
1408 tv.tv_usec = 0;
1409 retval = select(Sock+1,&rfds,NULL,NULL,&tv);
1410 if(retval != 1)
1411 return found;
1412 res = recv(Sock,buf+BufPos,sizeof(buf)-BufPos-1,0);
1413 }
1414 return found;
1415 }
1416
SU_EncodeURL(const char URL_in[],char URL_out[],int URL_out_len)1417 char *SU_EncodeURL(const char URL_in[],char URL_out[],int URL_out_len)
1418 {
1419 char NB[10];
1420 int i,pos;
1421
1422 pos = 0;
1423 for(i=0;i<(int)strlen(URL_in);i++)
1424 {
1425 if((URL_in[i] >='!') && (URL_in[i] <='~'))
1426 {
1427 if((pos+1) >= URL_out_len)
1428 {
1429 break;
1430 }
1431 URL_out[pos++] = URL_in[i];
1432 }
1433 else
1434 {
1435 if((pos+3) >= URL_out_len)
1436 {
1437 break;
1438 }
1439 URL_out[pos++] = '%';
1440 SU_snprintf(NB,sizeof(NB),"%.2x",URL_in[i]);
1441 URL_out[pos++] = NB[strlen(NB)-2];
1442 URL_out[pos++] = NB[strlen(NB)-1];
1443 }
1444 }
1445 URL_out[pos] = 0;
1446 return URL_out;
1447 }
1448
SU_ExecuteActions(SU_PList Actions)1449 int SU_ExecuteActions(SU_PList Actions)
1450 {
1451 SU_PList Ptr = Actions;
1452 SU_PList ActRec = NULL;
1453 SU_PAnswer Ans;
1454 SU_THTTPActions Act;
1455 char URL_OUT[URL_BUF_SIZE];
1456 int Sock;
1457 char *ptr;
1458 int PortConnect;
1459 SSL *ssl = NULL;
1460 bool ssl_mode = false;
1461 int Code;
1462 char *proxy_string;
1463
1464 while(Ptr != NULL)
1465 {
1466 if(((SU_PHTTPActions)Ptr->Data)->Sleep != 0)
1467 {
1468 #ifdef __unix__
1469 if(SU_DebugLevel >= 1)
1470 printf("SkyUtils_SU_ExecuteActions : Sleeping %d sec before sending command\n",((SU_PHTTPActions)Ptr->Data)->Sleep);
1471 sleep(((SU_PHTTPActions)Ptr->Data)->Sleep); /* Sleeping */
1472 #else /* !__unix__ */
1473 Sleep(((SU_PHTTPActions)Ptr->Data)->Sleep*1000); /* Sleeping */
1474 #endif /* __unix__ */
1475 }
1476 switch(((SU_PHTTPActions)Ptr->Data)->Command)
1477 {
1478 case ACT_GET :
1479 case ACT_POST :
1480 case ACT_PUT :
1481 case ACT_DELETE :
1482 Code = GetHostFromURL(((SU_PHTTPActions)Ptr->Data)->URL,((SU_PHTTPActions)Ptr->Data)->Host,sizeof(((SU_PHTTPActions)Ptr->Data)->Host),(SW_Proxy_String != NULL),URL_OUT,&PortConnect,((SU_PHTTPActions)Ptr->Data)->Host,&ssl_mode);
1483 if(Code != 0)
1484 return Code;
1485 ((SU_PHTTPActions)Ptr->Data)->SSL = ssl_mode;
1486 if(((SU_PHTTPActions)Ptr->Data)->CB.OnSendingCommand != NULL)
1487 ((SU_PHTTPActions)Ptr->Data)->CB.OnSendingCommand((SU_PHTTPActions)Ptr->Data);
1488 /* Get URL_OUT once again, if 'Act' has been modified in OnSendingCommand */
1489 Code = GetHostFromURL(((SU_PHTTPActions)Ptr->Data)->URL,((SU_PHTTPActions)Ptr->Data)->Host,sizeof(((SU_PHTTPActions)Ptr->Data)->Host),(SW_Proxy_String != NULL),URL_OUT,&PortConnect,"",&ssl_mode);
1490 SU_strcpy(((SU_PHTTPActions)Ptr->Data)->URL,URL_OUT,sizeof(URL_OUT));
1491 if(SW_Proxy_String != NULL)
1492 {
1493 #ifdef __unix__
1494 if(SU_DebugLevel >= 1)
1495 {
1496 if(SW_Proxy_User == NULL)
1497 printf("SkyUtils_SU_ExecuteActions : Using proxy: %s, port %d\n",SW_Proxy_String,SW_Proxy_Port);
1498 else
1499 printf("SkyUtils_SU_ExecuteActions : Using proxy: %s, with user %s [%s], port %d\n",SW_Proxy_String,SW_Proxy_User,SW_Proxy_Password,SW_Proxy_Port);
1500 }
1501 #endif /* __unix__ */
1502 Sock = CreateConnection(SW_Proxy_String,SW_Proxy_Port,NULL); /* Not using SSL struct with a proxy */
1503 }
1504 else
1505 Sock = CreateConnection(((SU_PHTTPActions)Ptr->Data)->Host,PortConnect,ssl_mode?&ssl:NULL);
1506 if(Sock < 0)
1507 {
1508 printf("SkyUtils_SU_ExecuteActions Error : Cannot connect to the host\n");
1509 return(-1);
1510 }
1511 proxy_string = SW_Proxy_String;
1512 #ifdef SU_USE_SSL
1513 if((SW_Proxy_String != NULL) && ssl_mode) /* If proxy AND ssl, must send a CONNECT message to the proxy */
1514 {
1515 char errormsg[1024];
1516 #ifdef __unix__
1517 if(SU_DebugLevel >= 1)
1518 {
1519 printf("SkyUtils_SU_ExecuteActions : Sending SSL CONNECT to the proxy, for %s:%d\n",((SU_PHTTPActions)Ptr->Data)->Host,GetPortFromHost(((SU_PHTTPActions)Ptr->Data)->Host,true));
1520 }
1521 #endif /* __unix__ */
1522 if(!SU_SendProxySSLConnect(Sock,((SU_PHTTPActions)Ptr->Data)->Host,GetPortFromHost(((SU_PHTTPActions)Ptr->Data)->Host,true),&Code))
1523 {
1524 printf("SkyUtils_SU_ExecuteActions Error : Cannot send CONNECT message to the proxy : Code=%d\n",Code);
1525 return(-1);
1526 }
1527 #ifdef __unix__
1528 if(SU_DebugLevel >= 1)
1529 {
1530 printf("SkyUtils_SU_ExecuteActions : SSL CONNECT successfully sent !\n");
1531 }
1532 #endif /* __unix__ */
1533 ssl = SU_SSL_Connect(Sock,errormsg);
1534 if(ssl == NULL)
1535 {
1536 printf("SkyUtils_SU_ExecuteActions Error : Cannot create SSL connection : %s\n",errormsg);
1537 return(-1);
1538 }
1539 proxy_string = NULL;
1540 /* Transforming URL as if we were not using a proxy */
1541 Code = GetHostFromURL(((SU_PHTTPActions)Ptr->Data)->URL,((SU_PHTTPActions)Ptr->Data)->Host,sizeof(((SU_PHTTPActions)Ptr->Data)->Host),false,URL_OUT,&PortConnect,"",&ssl_mode);
1542 if(Code != 0)
1543 return Code;
1544 SU_strcpy(((SU_PHTTPActions)Ptr->Data)->URL,URL_OUT,sizeof(URL_OUT));
1545 }
1546 #endif /* SU_USE_SSL */
1547 if(SendCommand(Sock,(SU_PHTTPActions)Ptr->Data,(proxy_string != NULL),ssl_mode?ssl:NULL)) /* If SSL && proxy, simulate NO PROXY */
1548 {
1549 Ans = WaitForAnswer(Sock,((SU_PHTTPActions)Ptr->Data),(proxy_string != NULL),ssl_mode?ssl:NULL);
1550 if(Ans == NULL)
1551 {
1552 printf("SkyUtils_SU_ExecuteActions Error : Connection timed out\n");
1553 return(-2);
1554 }
1555 if(((SU_PHTTPActions)Ptr->Data)->CB.OnAnswer != NULL)
1556 ((SU_PHTTPActions)Ptr->Data)->CB.OnAnswer(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1557 #ifdef __unix__
1558 if(SU_DebugLevel >= 2)
1559 printf("SkyUtils_SU_ExecuteActions : Found Code : %d\n",Ans->Code);
1560 #endif /* __unix__ */
1561 switch(Ans->Code)
1562 {
1563 case 200 : /* Ok reply */
1564 if(((SU_PHTTPActions)Ptr->Data)->CB.OnOk != NULL)
1565 ((SU_PHTTPActions)Ptr->Data)->CB.OnOk(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1566 break;
1567 case 201 : /* Created */
1568 if(((SU_PHTTPActions)Ptr->Data)->CB.OnCreated != NULL)
1569 ((SU_PHTTPActions)Ptr->Data)->CB.OnCreated(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1570 break;
1571 case 202 : /* Modified */
1572 if(((SU_PHTTPActions)Ptr->Data)->CB.OnModified != NULL)
1573 ((SU_PHTTPActions)Ptr->Data)->CB.OnModified(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1574 break;
1575 case 301 : /* Moved */
1576 case 302 : /* Moved */
1577 case 303 : /* Moved */
1578 if(((SU_PHTTPActions)Ptr->Data)->CB.OnMoved != NULL)
1579 ((SU_PHTTPActions)Ptr->Data)->CB.OnMoved(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1580 memset(&Act,0,sizeof(Act));
1581 if(((SU_PHTTPActions)Ptr->Data)->FileName)
1582 Act.FileName = SU_strdup(((SU_PHTTPActions)Ptr->Data)->FileName);
1583 Act.User = ((SU_PHTTPActions)Ptr->Data)->User;
1584 memcpy(&Act.CB,&((SU_PHTTPActions)Ptr->Data)->CB,sizeof(Act.CB));
1585 Act.Command = ACT_GET;
1586 if(SU_nocasestrstr(Ans->Location,"http://") != Ans->Location) /* Relative path */
1587 {
1588 if(SU_nocasestrstr(Ans->Location,"https://") != Ans->Location) /* Really a relative path */
1589 {
1590 ptr = SU_AddLocationToUrl(((SU_PHTTPActions)Ptr->Data)->URL,((SU_PHTTPActions)Ptr->Data)->Host,Ans->Location,((SU_PHTTPActions)Ptr->Data)->SSL);
1591 free(Ans->Location);
1592 Ans->Location = ptr;
1593 }
1594 }
1595 /* Let say we use a proxy, so we have less code to execute :o) */
1596 Code = GetHostFromURL(Ans->Location,((SU_PHTTPActions)Ptr->Data)->Host,sizeof(Act.Host),true,Act.URL,&PortConnect,"",&ssl_mode);
1597 if(Code != 0)
1598 return Code;
1599 SU_EncodeURL(Ans->Location,Act.URL,sizeof(Act.URL));
1600 Act.URL_Params = NULL;
1601 if(((SU_PHTTPActions)Ptr->Data)->Referer != NULL)
1602 Act.Referer = ((SU_PHTTPActions)Ptr->Data)->Referer;
1603 else
1604 Act.Referer = ((SU_PHTTPActions)Ptr->Data)->URL;
1605 ActRec = SU_AddElementHead(NULL,&Act);
1606 SU_ExecuteActions(ActRec);
1607 if(Act.FileName)
1608 free(Act.FileName);
1609 ActRec = SU_DelElementHead(ActRec);
1610 break;
1611 case 403 : /* Forbidden */
1612 if(((SU_PHTTPActions)Ptr->Data)->CB.OnForbidden != NULL)
1613 ((SU_PHTTPActions)Ptr->Data)->CB.OnForbidden(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1614 break;
1615 case 404 : /* Page Not Found */
1616 if(((SU_PHTTPActions)Ptr->Data)->CB.OnNotFound != NULL)
1617 ((SU_PHTTPActions)Ptr->Data)->CB.OnNotFound(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1618 break;
1619 case 413 : /* Request entity too large */
1620 if(((SU_PHTTPActions)Ptr->Data)->CB.OnTooBig != NULL)
1621 ((SU_PHTTPActions)Ptr->Data)->CB.OnTooBig(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1622 break;
1623 case 503 : /* Unknown Host */
1624 if(((SU_PHTTPActions)Ptr->Data)->CB.OnUnknownHost != NULL)
1625 ((SU_PHTTPActions)Ptr->Data)->CB.OnUnknownHost(Ans,((SU_PHTTPActions)Ptr->Data)->User);
1626 break;
1627 default : /* Other */
1628 if(((SU_PHTTPActions)Ptr->Data)->CB.OnOtherReply != NULL)
1629 ((SU_PHTTPActions)Ptr->Data)->CB.OnOtherReply(Ans,Ans->Code,((SU_PHTTPActions)Ptr->Data)->User);
1630 break;
1631 }
1632 FreeAnswer(Ans);
1633 }
1634 break;
1635 default :
1636 printf("SkyUtils_SU_ExecuteActions Warning : Unknown Action !!\n");
1637 }
1638 Ptr = Ptr->Next;
1639 }
1640 return 0;
1641 }
1642
SU_FreePart(SU_PHTTPPart Part)1643 void SU_FreePart(SU_PHTTPPart Part)
1644 {
1645 if(Part->Header)
1646 free(Part->Header);
1647 if(Part->FileName)
1648 free(Part->FileName);
1649 if(Part->Data)
1650 free(Part->Data);
1651 free(Part);
1652 }
1653
SU_FreeAction(SU_PHTTPActions Act)1654 void SU_FreeAction(SU_PHTTPActions Act)
1655 {
1656 if(Act->URL_Params != NULL)
1657 free(Act->URL_Params);
1658 if(Act->Post_Data != NULL)
1659 free(Act->Post_Data);
1660 if(Act->FileName != NULL)
1661 free(Act->FileName);
1662 if(Act->Referer != NULL)
1663 free(Act->Referer);
1664 if(Act->ContentType)
1665 free(Act->ContentType);
1666 if(Act->MultiParts)
1667 {
1668 SU_PList Ptr = Act->MultiParts;
1669 while(Ptr != NULL)
1670 {
1671 SU_FreePart(Ptr->Data);
1672 Ptr = Ptr->Next;
1673 }
1674 SU_FreeList(Act->MultiParts);
1675 }
1676 free(Act);
1677 }
1678
SU_GetInput(char * html)1679 SU_PInput SU_GetInput(char *html)
1680 {
1681 SW_GetInput_String = html;
1682 return SU_GetNextInput();
1683 }
1684
SU_GetNextInput(void)1685 SU_PInput SU_GetNextInput(void)
1686 {
1687 char *p,*ps,*pt,*q,*r,*s,*tmp,buf[500];
1688 char c,toto[3],res;
1689 int len;
1690 SU_PInput In;
1691 bool textarea = false;
1692
1693 p = SU_nocasestrstr(SW_GetInput_String,"<input");
1694 ps = SU_nocasestrstr(SW_GetInput_String,"<select");
1695 pt = SU_nocasestrstr(SW_GetInput_String,"<textarea");
1696 if((pt != NULL) && ((pt<p) || (p == NULL)) && ((pt<ps) || (ps == NULL))) /* Textarea found first */
1697 {
1698 p = pt+3; /* +3 to adjust from sizeof("textarea") to sizeof("input") */
1699 textarea = true;
1700 }
1701 if(((p>ps) || (p == NULL)) && (ps != NULL))
1702 p = ps+1; /* +1 to adjust from sizeof("select") to sizeof("input") */
1703 if(p == NULL)
1704 return NULL;
1705 s = p;
1706 In = (SU_PInput) malloc(sizeof(SU_TInput));
1707 memset(In,0,sizeof(SU_TInput));
1708 p+=7;
1709 r = strchr(p,'>');
1710 /* Now parse input tags */
1711 toto[0] = '=';
1712 toto[1] = ' ';
1713 toto[2] = 0;
1714 while(p[0] != '>')
1715 {
1716 while(*p == ' ')
1717 p++;
1718 q = SU_strchrl(p,toto,&res);
1719 if(q == NULL)
1720 break;
1721 if(q > r) /* Attention ici, si on veux plus tard recup les non Name=Value */
1722 break;
1723 len = q-p;
1724 if(len >= sizeof(buf))
1725 len = sizeof(buf) - 1;
1726 memcpy(buf,p,len);
1727 buf[len] = 0;
1728 /* buf contient la partie Name de Name=Value */
1729 p = SU_TrimLeft(q + 1);
1730 if(res == ' ')
1731 {
1732 if(p[0] != '=')
1733 continue;
1734 else
1735 p = SU_TrimLeft(p+1);
1736 }
1737 while((len > 0) && (buf[len-1] == ' '))
1738 {
1739 len--;
1740 buf[len] = 0; /* Remove trailing spaces */
1741 }
1742 if((strchr(buf,' ') == NULL) && (res != '>')) /* Si on a bien a faire a un Name=Value */
1743 {
1744 if(p[0] == '"') /* Si la partie Value est une chaine */
1745 {
1746 c = '"';
1747 p++;
1748 }
1749 else if(p[0] == '\'') /* Si la partie Value est une chaine */
1750 {
1751 c = '\'';
1752 p++;
1753 }
1754 else
1755 c = ' ';
1756 q = strchr(p,c);
1757 if(q == NULL)
1758 break;
1759 if(q > r)
1760 {
1761 if((c == '"') || (c == '\'')) /* '>' must be inside the string */
1762 r = strchr(r+1,'>');
1763 else
1764 q = r;
1765 }
1766 len = q-p;
1767 if(len <= 0)
1768 continue;
1769 tmp = (char *) malloc(len+1);
1770 memcpy(tmp,p,len);
1771 tmp[len] = 0;
1772 p = q;
1773 if((c == '"') || (c == '\'')) /* Si la partie Value est une chaine */
1774 p++;
1775 if(SU_nocasestrstr(buf,"type") == buf)
1776 In->Type = tmp;
1777 else if(SU_nocasestrstr(buf,"name") == buf)
1778 In->Name = tmp;
1779 else if(SU_nocasestrstr(buf,"value") == buf)
1780 In->Value = tmp;
1781 else
1782 free(tmp);
1783 }
1784 }
1785 if(textarea)
1786 {
1787 if(In->Type == NULL)
1788 In->Type = SU_strdup("textarea");
1789 p = SU_nocasestrstr(r+1,"</textarea>");
1790 if(p == NULL)
1791 {
1792 if(In->Name != NULL)
1793 {
1794 free(In->Name);
1795 In->Name = NULL;
1796 }
1797 }
1798 else
1799 {
1800 if(In->Value != NULL)
1801 free(In->Value);
1802 In->Value = (char *) malloc(p-r);
1803 SU_strcpy(In->Value,r+1,p-r);
1804 r = p+2;
1805 }
1806 }
1807 if(r != NULL)
1808 SW_GetInput_String = r;
1809 else
1810 SW_GetInput_String = s+6;
1811 if(In->Name == NULL)
1812 {
1813 SU_FreeInput(In);
1814 return SU_GetNextInput();
1815 }
1816 return In;
1817 }
1818
SU_FreeInput(SU_PInput In)1819 void SU_FreeInput(SU_PInput In)
1820 {
1821 if(In->Type != NULL)
1822 free(In->Type);
1823 if(In->Name != NULL)
1824 free(In->Name);
1825 if(In->Value != NULL)
1826 free(In->Value);
1827 free(In);
1828 }
1829
SU_GetImage(char * html)1830 SU_PImage SU_GetImage(char *html)
1831 {
1832 SW_GetImage_String = html;
1833 return SU_GetNextImage();
1834 }
1835
SU_GetNextImage(void)1836 SU_PImage SU_GetNextImage(void)
1837 {
1838 char *p,*q,*tmp;
1839 int len;
1840 char c;
1841 SU_PImage Im;
1842
1843 p = SU_nocasestrstr(SW_GetImage_String,"img src");
1844 if(p == NULL)
1845 return NULL;
1846 Im = (SU_PImage) malloc(sizeof(SU_TImage));
1847 memset(Im,0,sizeof(SU_TImage));
1848 p+=7;
1849 while(*p == ' ')
1850 p++;
1851 p++; /* zap le '=' */
1852 while(*p == ' ')
1853 p++; /* zap les espaces apres le '=' */
1854 if(*p == '"')
1855 {
1856 c = '"';
1857 p++; /* zap le '"' si c'est une chaine */
1858 }
1859 else if(*p == '\'')
1860 {
1861 c = '\'';
1862 p++; /* zap le '\'' si c'est une chaine */
1863 }
1864 else
1865 c = ' ';
1866 q = strchr(p,c);
1867 len = q-p;
1868 tmp = (char *) malloc(len+1);
1869 memcpy(tmp,p,len);
1870 tmp[len] = 0;
1871 p = q;
1872 if((c == '"') || (c == '\'')) /* Si la partie Value est une chaine */
1873 p++;
1874 Im->Src = tmp;
1875 while(p[0] != '>')
1876 {
1877 /* Faudrait boucler ici pour recup le Name eventuellement */
1878 p++;
1879 }
1880
1881 SW_GetImage_String = p;
1882 return Im;
1883 }
1884
SU_FreeImage(SU_PImage Im)1885 void SU_FreeImage(SU_PImage Im)
1886 {
1887 if(Im->Src != NULL)
1888 free(Im->Src);
1889 if(Im->Name != NULL)
1890 free(Im->Name);
1891 free(Im);
1892 }
1893
SU_RetrieveLink(const char URL[],const char Ans[],const char link[],const int index)1894 SU_PHTTPActions SU_RetrieveLink(const char URL[],const char Ans[],const char link[],const int index)
1895 {
1896 char *p,*q,c,*tmp,*tmp2,*rp,*rs;
1897 SU_PHTTPActions Act;
1898 int i;
1899 bool found;
1900
1901 p = (char *)Ans-1;
1902 for(i=1;i<=index;i++)
1903 p = strstr(p+1,link);
1904 if(p == NULL)
1905 return NULL;
1906 while(strncasecmp(p,"href",4) != 0)
1907 p--;
1908 p+=4;
1909 p = SU_TrimLeft(p); /* Remove spaces */
1910 p++; /* Zap '=' */
1911 p = SU_TrimLeft(p); /* Remove spaces */
1912 if(p[0] == '"')
1913 {
1914 c = '"';
1915 p++; /* Zap '"' */
1916 }
1917 else if(p[0] == '\'')
1918 {
1919 c = '\'';
1920 p++; /* Zap '\'' */
1921 }
1922 else
1923 c = ' ';
1924 q = strchr(p,c);
1925 tmp = (char *) malloc(q-p+1);
1926 SU_strcpy(tmp,p,q-p+1);
1927
1928 Act = (SU_PHTTPActions) malloc(sizeof(SU_THTTPActions));
1929 memset(Act,0,sizeof(SU_THTTPActions));
1930 Act->Command = ACT_GET;
1931 /* URL in tmp, but may be relative */
1932 if(strncasecmp(tmp,"http",4) == 0) /* Absolute */
1933 strncpy(Act->URL,tmp,sizeof(Act->URL));
1934 else
1935 {
1936 if(tmp[0] == '/') /* Root of the host */
1937 {
1938 #ifdef __unix__
1939 tmp2 = strchr(URL+7,'/');
1940 #else /* !__unix__ */
1941 tmp2 = strchr((char *)URL+7,'/');
1942 #endif /* __unix__ */
1943 if(tmp2 == NULL) /* Already at the root of the site */
1944 {
1945 SU_strcpy(Act->URL,URL,sizeof(Act->URL));
1946 SU_strcat(Act->URL,tmp,sizeof(Act->URL));
1947 }
1948 else
1949 {
1950 if((tmp2-URL+1) >= sizeof(Act->URL))
1951 printf("SkyUtils_SU_RetrieveLink Warning : URL replacement in SU_RetrieveLink is bigger than sizeof(URL). Results will be unpredictable\n");
1952 else
1953 SU_strcpy(Act->URL,URL,tmp2-URL+1); /* Copy the root part of URL */
1954 SU_strcat(Act->URL,tmp,sizeof(Act->URL));
1955 }
1956 }
1957 else
1958 {
1959 tmp2 = tmp;
1960 strncpy(Act->URL,URL,sizeof(Act->URL));
1961 /* If / at the end of URL, remove it */
1962 if(Act->URL[strlen(Act->URL)-1] == '/')
1963 Act->URL[strlen(Act->URL)-1] = 0;
1964 /* If end of URL if a file, remove it */
1965 rp = strrchr(Act->URL,'.');
1966 rs = strrchr(Act->URL,'/');
1967 if(rp > rs)
1968 rs[0] = 0;
1969 /* For each ../ remove it from URL */
1970 while(strncasecmp(tmp2,"../",3) == 0)
1971 {
1972 tmp2+=3;
1973 i = strlen(Act->URL) - 1;
1974 found = false;
1975 while(i >= 0)
1976 {
1977 if(Act->URL[i] == '/')
1978 {
1979 found = true;
1980 Act->URL[i] = 0;
1981 break;
1982 }
1983 i--;
1984 }
1985 if(!found)
1986 {
1987 free(tmp);
1988 free(Act);
1989 return NULL;
1990 }
1991 }
1992 /* If no / at the end of URL, add it */
1993 if(Act->URL[strlen(Act->URL)-1] != '/')
1994 SU_strcat(Act->URL,"/",sizeof(Act->URL));
1995 /* Cat URL and dest */
1996 SU_strcat(Act->URL,tmp2,sizeof(Act->URL));
1997 }
1998 }
1999 free(tmp);
2000 return Act;
2001 }
2002
2003 /* Code added by Pierre Bacquet (pbacquet@delta.fr) */
SU_RetrieveFrame(const char URL[],const char Ans[],const char framename[])2004 SU_PHTTPActions SU_RetrieveFrame(const char URL[],const char Ans[],const char framename[])
2005 {
2006 char *p,*q,c,*tmp,*tmp2,*rp,*rs;
2007 SU_PHTTPActions Act;
2008 int i;
2009 bool found;
2010 char pattern[1024];
2011
2012 SU_snprintf(pattern,sizeof(pattern),"FRAME NAME=%s", framename);
2013
2014 p = SU_nocasestrstr((char *)Ans,pattern);
2015 if(p == NULL)
2016 return NULL;
2017 while(strncasecmp(p,"src",3) != 0)
2018 p++;
2019 p+=3;
2020 p = SU_TrimLeft(p); /* Remove spaces */
2021 p++; /* Zap '=' */
2022 p = SU_TrimLeft(p); /* Remove spaces */
2023 if(p[0] == '"')
2024 {
2025 c = '"';
2026 p++; /* Zap '"' */
2027 }
2028 else if(p[0] == '\'')
2029 {
2030 c = '\'';
2031 p++; /* Zap '\'' */
2032 }
2033 else
2034 c = ' ';
2035 q = strchr(p,c);
2036 tmp = (char *) malloc(q-p+1);
2037 SU_strcpy(tmp,p,q-p+1);
2038
2039 Act = (SU_PHTTPActions) malloc(sizeof(SU_THTTPActions));
2040 memset(Act,0,sizeof(SU_THTTPActions));
2041 Act->Command = ACT_GET;
2042 /* URL in tmp, but may be relative */
2043 if(strncasecmp(tmp,"http",4) == 0) /* Absolute */
2044 strncpy(Act->URL,tmp,sizeof(Act->URL));
2045 else
2046 {
2047 if(tmp[0] == '/') /* Root of the host */
2048 {
2049 #ifdef __unix__
2050 tmp2 = strchr(URL+7,'/');
2051 #else /* !__unix__ */
2052 tmp2 = strchr((char *)URL+7,'/');
2053 #endif /* __unix__ */
2054 if(tmp2 == NULL) /* Already at the root of the site */
2055 {
2056 SU_strcpy(Act->URL,URL,sizeof(Act->URL));
2057 SU_strcat(Act->URL,tmp,sizeof(Act->URL));
2058 }
2059 else
2060 {
2061 if((tmp2-URL+1) >= sizeof(Act->URL))
2062 printf("SkyUtils_SU_RetrieveFrame Warning : URL replacement in SU_RetrieveFrame is bigger than sizeof(URL). Results will be unpredictable\n");
2063 else
2064 SU_strcpy(Act->URL,URL,tmp2-URL+1); /* Copy the root part of URL */
2065 SU_strcat(Act->URL,tmp,sizeof(Act->URL));
2066 }
2067 }
2068 else
2069 {
2070 tmp2 = tmp;
2071 strncpy(Act->URL,URL,sizeof(Act->URL));
2072 /* If / at the end of URL, remove it */
2073 if(Act->URL[strlen(Act->URL)-1] == '/')
2074 Act->URL[strlen(Act->URL)-1] = 0;
2075 /* If end of URL if a file, remove it */
2076 rp = strrchr(Act->URL,'.');
2077 rs = strrchr(Act->URL,'/');
2078 if(rp > rs)
2079 rs[0] = 0;
2080 /* For each ../ remove it from URL */
2081 while(strncasecmp(tmp2,"../",3) == 0)
2082 {
2083 tmp2+=3;
2084 i = strlen(Act->URL) - 1;
2085 found = false;
2086 while(i >= 0)
2087 {
2088 if(Act->URL[i] == '/')
2089 {
2090 found = true;
2091 Act->URL[i] = 0;
2092 break;
2093 }
2094 i--;
2095 }
2096 if(!found)
2097 {
2098 free(tmp);
2099 free(Act);
2100 return NULL;
2101 }
2102 }
2103 /* If no / at the end of URL, add it */
2104 if(Act->URL[strlen(Act->URL)-1] != '/')
2105 SU_strcat(Act->URL,"/",sizeof(Act->URL));
2106 /* Cat URL and dest */
2107 SU_strcat(Act->URL,tmp2,sizeof(Act->URL));
2108 }
2109 }
2110 free(tmp);
2111 return Act;
2112 }
2113
2114 /* Retrieve document.forms[num] */
SU_RetrieveForm(const char Ans[],const int num)2115 SU_PForm SU_RetrieveForm(const char Ans[],const int num)
2116 {
2117 char *p,*ps,*pt,*q,*r,*saf,*parse,*tmp,c,buf[500];
2118 int i,len;
2119 SU_PInput In;
2120 SU_PForm Form;
2121 SU_PList Ptr;
2122 char toto[3],res;
2123 bool textarea = false;
2124
2125 p = SU_nocasestrstr((char *)Ans,"<form");
2126 if(p == NULL)
2127 return NULL;
2128 for(i=0;i<num;i++)
2129 {
2130 p = SU_nocasestrstr(p,"/form");
2131 if(p == NULL)
2132 return NULL;
2133 p = SU_nocasestrstr(p,"<form");
2134 if(p == NULL)
2135 return NULL;
2136 }
2137 q = SU_nocasestrstr(p,"/form");
2138 if(q == NULL)
2139 return NULL;
2140 saf = (char *) malloc(q-p+1);
2141 toto[1] = '>';
2142 toto[2] = 0;
2143 SU_strcpy(saf,p,q-p+1);
2144 /* Got the full form in saf */
2145 parse = saf;
2146 Form = (SU_PForm) malloc(sizeof(SU_TForm));
2147 memset(Form,0,sizeof(SU_TForm));
2148 Ptr = NULL;
2149 p = SU_TrimLeft(parse+5);
2150 /* Now parse form tag */
2151 while(p[0] != '>')
2152 {
2153 if(strncasecmp(p,"method",6) == 0)
2154 {
2155 p = SU_TrimLeft(p+6);
2156 p++; /* Zap '=' */
2157 p = SU_TrimLeft(p);
2158 if(p[0] == '"')
2159 {
2160 c = '"';
2161 p++; /* Zap '"' */
2162 }
2163 else if(p[0] == '\'')
2164 {
2165 c = '\'';
2166 p++; /* Zap '\'' */
2167 }
2168 else
2169 c = ' ';
2170 toto[0] = c;
2171 q = SU_strchrl(p,toto,&res);
2172 if(q == NULL)
2173 break;
2174 tmp = (char *) malloc(q-p+1);
2175 SU_strcpy(tmp,p,q-p+1);
2176 Form->Method = tmp;
2177 p = q;
2178 if((c == '"') || (c == '\''))
2179 p++; /* Zap '"' */
2180 }
2181 else if(strncasecmp(p,"name",4) == 0)
2182 {
2183 p = SU_TrimLeft(p+4);
2184 p++; /* Zap '=' */
2185 p = SU_TrimLeft(p);
2186 if(p[0] == '"')
2187 {
2188 c = '"';
2189 p++; /* Zap '"' */
2190 }
2191 else if(p[0] == '\'')
2192 {
2193 c = '\'';
2194 p++; /* Zap '\'' */
2195 }
2196 else
2197 c = ' ';
2198 toto[0] = c;
2199 q = SU_strchrl(p,toto,&res);
2200 if(q == NULL)
2201 break;
2202 tmp = (char *) malloc(q-p+1);
2203 SU_strcpy(tmp,p,q-p+1);
2204 Form->Name = tmp;
2205 p = q;
2206 if((c == '"') || (c == '\''))
2207 p++; /* Zap '"' */
2208 }
2209 else if(strncasecmp(p,"action",6) == 0)
2210 {
2211 p = SU_TrimLeft(p+6);
2212 p++; /* Zap '=' */
2213 p = SU_TrimLeft(p);
2214 if(p[0] == '"')
2215 {
2216 c = '"';
2217 p++; /* Zap '"' */
2218 }
2219 else if(p[0] == '\'')
2220 {
2221 c = '\'';
2222 p++; /* Zap '\'' */
2223 }
2224 else
2225 c = ' ';
2226 toto[0] = c;
2227 q = SU_strchrl(p,toto,&res);
2228 if(q == NULL)
2229 break;
2230 tmp = (char *) malloc(q-p+1);
2231 SU_strcpy(tmp,p,q-p+1);
2232 Form->Action = tmp;
2233 p = q;
2234 if((c == '"') || (c == '\''))
2235 p++; /* Zap '"' */
2236 }
2237 else
2238 {
2239 q = strchr(p,' ');
2240 r = strchr(p,'>');
2241 if((q == NULL) || (r == NULL))
2242 break;
2243 if(r < q)
2244 break;
2245 else
2246 p = q;
2247 }
2248 p = SU_TrimLeft(p);
2249 }
2250 #ifdef __unix__
2251 if(SU_DebugLevel >= 3)
2252 printf("SkyUtils_SU_RetrieveForm : Info for forms[%d] : Method=%s - Name=%s - Action=%s\n",num,(Form->Method == NULL)?"(null)":Form->Method,(Form->Name == NULL)?"(null)":Form->Name,(Form->Action == NULL)?"(null)":Form->Action);
2253 #endif /* __unix__ */
2254
2255 p = SU_nocasestrstr(parse,"<input");
2256 ps = SU_nocasestrstr(parse,"<select");
2257 pt = SU_nocasestrstr(parse,"<textarea");
2258 if((pt != NULL) && ((pt<p) || (p == NULL)) && ((pt<ps) || (ps == NULL))) /* Textarea found first */
2259 {
2260 p = pt+3; /* +3 to adjust from sizeof("textarea") to sizeof("input") */
2261 textarea = true;
2262 }
2263 if(((p>ps) || (p == NULL)) && (ps != NULL))
2264 p = ps+1; /* +1 to adjust from sizeof("select") to sizeof("input") */
2265 while(p != NULL)
2266 {
2267 In = (SU_PInput) malloc(sizeof(SU_TInput));
2268 memset(In,0,sizeof(SU_TInput));
2269 p = SU_TrimLeft(p+6);
2270 /* Now parse input tags */
2271 r = strchr(p,'>');
2272 toto[0] = '=';
2273 toto[1] = ' ';
2274 while(p[0] != '>')
2275 {
2276 q = SU_strchrl(p,toto,&res);
2277 if(q == NULL)
2278 break;
2279 if(q > r) /* Attention ici, si on veux plus tard recup les non Name=Value */
2280 break;
2281 len = q-p;
2282 if(len >= sizeof(buf))
2283 len = sizeof(buf) - 1;
2284 memcpy(buf,p,len);
2285 buf[len] = 0;
2286 /* buf contient la partie Name de Name=Value */
2287 p = SU_TrimLeft(q + 1);
2288 if(res == ' ')
2289 {
2290 if(p[0] != '=')
2291 continue;
2292 else
2293 p = SU_TrimLeft(p+1);
2294 }
2295 while((len > 0) && (buf[len-1] == ' '))
2296 {
2297 len--;
2298 buf[len] = 0; /* Remove trailing spaces */
2299 }
2300 if((strchr(buf,' ') == NULL) && (res != '>')) /* Si on a bien a faire a un Name=Value */
2301 {
2302 if(p[0] == '"') /* Si la partie Value est une chaine */
2303 {
2304 c = '"';
2305 p++;
2306 }
2307 else if(p[0] == '\'') /* Si la partie Value est une chaine */
2308 {
2309 c = '\'';
2310 p++;
2311 }
2312 else
2313 c = ' ';
2314 q = strchr(p,c);
2315 if(q == NULL)
2316 q = r;
2317 if(q > r)
2318 {
2319 if((c == '"') || (c == '\'')) /* '>' must be inside the string */
2320 r = strchr(r+1,'>');
2321 else
2322 q = r;
2323 }
2324 len = q-p;
2325 if(len <= 0)
2326 continue;
2327 tmp = (char *) malloc(len+1);
2328 memcpy(tmp,p,len);
2329 tmp[len] = 0;
2330 p = q;
2331 if((c == '"') || (c == '\'')) /* Si la partie Value est une chaine */
2332 p++;
2333 if(SU_nocasestrstr(buf,"type") == buf)
2334 In->Type = tmp;
2335 else if(SU_nocasestrstr(buf,"name") == buf)
2336 In->Name = tmp;
2337 else if(SU_nocasestrstr(buf,"value") == buf)
2338 In->Value = tmp;
2339 else
2340 free(tmp);
2341 }
2342 p = SU_TrimLeft(p);
2343 }
2344 if(textarea)
2345 {
2346 if(In->Type == NULL)
2347 In->Type = SU_strdup("textarea");
2348 q = SU_nocasestrstr(p+1,"</textarea>");
2349 if(q == NULL)
2350 {
2351 if(In->Name != NULL)
2352 {
2353 free(In->Name);
2354 In->Name = NULL;
2355 }
2356 }
2357 else
2358 {
2359 if(In->Value != NULL)
2360 free(In->Value);
2361 In->Value = (char *) malloc(q-p);
2362 SU_strcpy(In->Value,r+1,q-p);
2363 p = q+2;
2364 }
2365 }
2366 if(In->Type == NULL)
2367 In->Type = SU_strdup("text");
2368 if(In->Name != NULL)
2369 {
2370 #ifdef __unix__
2371 if(SU_DebugLevel >= 3)
2372 printf("SkyUtils_SU_RetrieveForm : Adding INPUT to form[%d] : Type=%s - Name=%s - Value=%s\n",num,(In->Type == NULL)?"(null)":In->Type,(In->Name == NULL)?"(null)":In->Name,(In->Value == NULL)?"(null)":In->Value);
2373 #endif /* __unix__ */
2374 Ptr = SU_AddElementHead(Ptr,In);
2375 }
2376 else
2377 SU_FreeInput(In);
2378
2379 textarea = false;
2380 parse = p+1; /* Set parse to the end of INPUT (after the '>') */
2381 p = SU_nocasestrstr(parse,"<input");
2382 ps = SU_nocasestrstr(parse,"<select");
2383 pt = SU_nocasestrstr(parse,"<textarea");
2384 if((pt != NULL) && ((pt<p) || (p == NULL)) && ((pt<ps) || (ps == NULL))) /* Textarea found first */
2385 {
2386 p = pt+3; /* +3 to adjust from sizeof("textarea") to sizeof("input") */
2387 textarea = true;
2388 }
2389 if(((p>ps) || (p == NULL)) && (ps != NULL))
2390 p = ps+1; /* +1 to adjust from sizeof("select") to sizeof("input") */
2391 }
2392 free(saf);
2393 Form->Inputs = Ptr;
2394 return Form;
2395 }
2396
SU_FreeForm(SU_PForm Form)2397 void SU_FreeForm(SU_PForm Form)
2398 {
2399 SU_PList Ptr;
2400
2401 Ptr = Form->Inputs;
2402 while(Ptr != NULL)
2403 {
2404 SU_FreeInput((SU_PInput)Ptr->Data);
2405 Ptr = Ptr->Next;
2406 }
2407 SU_FreeList(Form->Inputs);
2408 if(Form->Method != NULL)
2409 free(Form->Method);
2410 if(Form->Name != NULL)
2411 free(Form->Name);
2412 if(Form->Action != NULL)
2413 free(Form->Action);
2414 }
2415
SU_AddLocationToUrl(const char * URL,const char * Host,const char * Location,bool ssl_mode)2416 char *SU_AddLocationToUrl(const char *URL,const char *Host,const char *Location,bool ssl_mode)
2417 {
2418 char *ptr = NULL;
2419 int len,i,pos = 0;
2420
2421 if(strncasecmp(Location,"http://",7) != 0) /* Relative path */
2422 {
2423 len = strlen(Host)+strlen(URL)+strlen(Location)+strlen("https://")+1;
2424 ptr = (char *) malloc(len);
2425 if(Location[0] == '/')
2426 { /* Relative path, but absolute on the site */
2427 SU_snprintf(ptr,len,"http%s://%s",ssl_mode?"s":"",Host);
2428 /* Remove trailing / if exists */
2429 if(ptr[strlen(ptr)-1] == '/' )
2430 ptr[strlen(ptr)-1] = 0;
2431 }
2432 else
2433 { /* Relative path from current directory */
2434 if(strncasecmp(URL,"http://",7) == 0) /* If using proxy, or if URL is already absolute */
2435 SU_strcpy(ptr,URL,len);
2436 else if(strncasecmp(URL,"https://",8) == 0) /* If using proxy, or if URL is already absolute - SSL */
2437 SU_strcpy(ptr,URL,len);
2438 else
2439 SU_snprintf(ptr,len,"http%s://%s%s",ssl_mode?"s":"",Host,URL);
2440
2441 if(strcmp(ptr+strlen("http://")+(ssl_mode?1:0),Host) == 0) /* If requested the root of the site */
2442 SU_strcat(ptr,"/",len);
2443 else
2444 {
2445 i = strlen(ptr) - 1;
2446 while(i>=0)
2447 {
2448 if(ptr[i] == '/')
2449 {
2450 ptr[i+1] = 0;
2451 break;
2452 }
2453 i--;
2454 }
2455 }
2456 /* Here, ptr have a trailing '/' */
2457 /* Check for '../' in Location */
2458 while(strncmp(Location+pos,"../",3) == 0)
2459 {
2460 i = strlen(ptr) - 1 - 1; /* Start from before the trailing '/' */
2461 while(i>=0)
2462 {
2463 if(ptr[i] == '/')
2464 {
2465 ptr[i+1] = 0; /* Go back a directory level */
2466 break;
2467 }
2468 i--;
2469 }
2470 pos += 3;
2471 }
2472 }
2473 SU_strcat(ptr,Location+pos,len);
2474 }
2475 else
2476 ptr = SU_strdup(Location);
2477 return ptr;
2478 }
2479
2480 /* Skips white spaces before the string, then extracts it */
SU_GetStringFromHtml(const char Ans[],const char TextBefore[])2481 char *SU_GetStringFromHtml(const char Ans[],const char TextBefore[])
2482 {
2483 char *p,*q,*tmp;
2484 char c;
2485 int len;
2486
2487 p = strstr(Ans,TextBefore);
2488 if(p == NULL)
2489 return NULL;
2490 p += strlen(TextBefore);
2491 while(p[0] == ' ') /* Remove spaces */
2492 p++;
2493
2494 if(p[0] == '"') /* If we have a string */
2495 {
2496 c = '"';
2497 p++;
2498 }
2499 else if(p[0] == '\'') /* If we have a string */
2500 {
2501 c = '\'';
2502 p++;
2503 }
2504 else
2505 c = ' ';
2506 q = strchr(p,c);
2507 if(q == NULL)
2508 return NULL;
2509 len = q-p;
2510 tmp = (char *) malloc(len+1);
2511 memcpy(tmp,p,len);
2512 tmp[len] = 0;
2513 return tmp;
2514 }
2515
SU_SetUserAgent(const char UA[])2516 void SU_SetUserAgent(const char UA[])
2517 {
2518 if(SW_UserAgent != NULL)
2519 free(SW_UserAgent);
2520 if(UA == NULL)
2521 SW_UserAgent = NULL;
2522 else
2523 SW_UserAgent = SU_strdup(UA);
2524 }
2525