1 /******************************************************************************/
2 /* Skyutils functions - Chained list,socket,string,utils,web,threads, archive */
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 #ifndef __SKY_UTILS_H__
24 #define __SKY_UTILS_H__
25 
26 #define SKYUTILS_VERSION "3.0"
27 #define SKYUTILS_AUTHOR "Chris Hutchinson"
28 
29 #if defined(__MACH__) || defined(_AIX)
30 #define __unix__
31 #endif /* __MACH__ || _AIX */
32 
33 #if defined(__cplusplus) && !defined(__BORLANDC__)
34 extern "C" {
35 #endif /* __cplusplus */
36 
37 #ifndef __cplusplus
38 #ifndef SU_BOOL_TYPE
39 #undef bool
40 typedef unsigned int bool;
41 #define true 1
42 #define false 0
43 #define SU_BOOL_TYPE
44 #endif /* !SU_BOOL_TYPE */
45 #endif /* !__cplusplus */
46 #define SU_BOOL unsigned int
47 
48 #ifndef SU_NO_INCLUDES
49 #include <errno.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <fcntl.h>
54 #include <signal.h>
55 #include <stdint.h>
56 #ifndef _WIN32
57 #include <unistd.h>
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 #include <sys/time.h>
61 #include <netinet/in.h>
62 #include <arpa/inet.h>
63 #include <netdb.h>
64 #include <sys/stat.h>
65 #include <pwd.h>
66 #include <grp.h>
67 #include <pthread.h>
68 #include <semaphore.h>
69 #define SU_SOCKET int
70 #else /* _WIN32 */
71 #if defined(_MT) && !defined(_REENTRANT)
72 #define _REENTRANT
73 #endif /* _MT */
74 #ifndef _WINSOCKAPI_
75 #include <winsock2.h>
76 #endif /* !_WINSOCKAPI_ */
77 #include <process.h>
78 #include <winbase.h>
79 #include <time.h>
80 #define SU_SOCKET SOCKET
81 #endif /* !_WIN32 */
82 #endif /* !SU_NO_INCLUDES */
83 
84 #ifdef MSG_NOSIGNAL
85 #define SU_MSG_NOSIGNAL MSG_NOSIGNAL
86 #else /* !MSG_NOSIGNAL */
87 #define SU_MSG_NOSIGNAL 0
88 #endif /* MSG_NOSIGNAL */
89 
90 #ifndef INADDR_NONE
91 #define INADDR_NONE -1
92 #endif /* !INADDR_NONE */
93 
94 #ifndef SOCKET_ERROR
95 #define SOCKET_ERROR -1
96 #endif /* !SOCKET_ERROR */
97 
98 #define SU_UDP_MAX_LENGTH 64000
99 
100 /* Portable types */
101 #if defined(_MSC_VER) || defined(__BORLANDC__)
102 typedef unsigned __int8 SU_u8;
103 typedef signed __int8 SU_s8;
104 typedef unsigned __int16 SU_u16;
105 typedef signed __int16 SU_s16;
106 typedef unsigned __int32 SU_u32;
107 typedef signed __int32 SU_s32;
108 typedef unsigned __int64 SU_u64;
109 typedef signed __int64 SU_s64;
110 #else /* !(_MSC_VER || __BORLANDC__) */
111 #if defined(__GNUC__) && defined (__linux__) && !defined(_WIN32) && !defined(__MINGW32__)
112 typedef u_int8_t SU_u8;
113 typedef int8_t SU_s8;
114 typedef u_int16_t SU_u16;
115 typedef int16_t SU_s16;
116 typedef u_int32_t SU_u32;
117 typedef int32_t SU_s32;
118 typedef u_int64_t SU_u64;
119 typedef int64_t SU_s64;
120 #else /* Not linux GCC */
121 typedef unsigned char SU_u8;
122 typedef signed char SU_s8;
123 typedef unsigned short SU_u16;
124 typedef signed short SU_s16;
125 typedef unsigned int SU_u32;
126 typedef signed int SU_s32;
127 typedef unsigned long long SU_u64;
128 typedef signed long long SU_s64;
129 #endif /* Linux GCC */
130 #endif /* _MSC_VER || __BORLANDC__ */
131 
132 
133 /* **************************************** */
134 /*            Chained list functions        */
135 /* **************************************** */
136 struct SU_SList;
137 
138 typedef struct SU_SList
139 {
140   struct SU_SList *Next;
141   void *Data;
142 } SU_TList, *SU_PList;
143 
144 SU_PList SU_AddElementTail(SU_PList,void *);
145 SU_PList SU_AddElementHead(SU_PList,void *);
146 SU_PList SU_AddElementPos(SU_PList List,int Pos,void *Elem); /* First element is at pos 0 */
147 SU_PList SU_DelElementElem(SU_PList,void *); /* This function does NOT free the element */
148 SU_PList SU_DelElementTail(SU_PList); /* This function does NOT free the element */
149 SU_PList SU_DelElementHead(SU_PList); /* This function does NOT free the element */
150 SU_PList SU_DelElementPos(SU_PList,int); /* This function does NOT free the element */ /* First element is at pos 0 */
151 void *SU_GetElementTail(SU_PList);
152 void *SU_GetElementHead(SU_PList);
153 void *SU_GetElementPos(SU_PList,int); /* First element is at pos 0 */
154 void SU_FreeList(SU_PList); /* This function does NOT free the elements */
155 void SU_FreeListElem(SU_PList); /* This function DOES free the elements */
156 unsigned int SU_ListCount(SU_PList);
157 
158 
159 /* **************************************** */
160 /*               Socket functions           */
161 /* **************************************** */
162 #ifndef SU_INCLUDE_NO_SOCKS
163 typedef struct
164 {
165   SU_SOCKET sock;
166   struct sockaddr_in SAddr;
167   void *User;
168 } SU_TServerInfo, *SU_PServerInfo;
169 
170 typedef struct
171 {
172   SU_SOCKET sock;
173   struct sockaddr_in SAddr;
174   void *User;
175 } SU_TClientSocket, *SU_PClientSocket;
176 
177 int SU_GetPortByName(char *port,char *proto); /* Returns port number from it's name */
178 char *SU_GetMachineName(char *RemoteHost);    /* Extracts the machine name from a full host */
179 char *SU_NameOfPort(char *Host);              /* Returns the host name matching the given ip */
180 char *SU_AdrsOfPort(char *Host);              /* Returns the ip adrs matching the given host */
181 
182 /*
183  Sends a buffer to socket.
184  Returns :
185   0  : Socket closed
186   -1 : Read error on socket (see SU_errno)
187   >0 : Total of bytes sent
188 */
189 int SU_SendTCPBuffer(SU_SOCKET sock,char *buf,int size);
190 /*
191  Reads a buffer from socket. If TimeOut is not NULL, select-timeout is used. If WaitForFullBuffer is true, don't return until error, or 'size' bytes has been read
192  Returns :
193   0  : Socket closed
194   -1 : Read error on socket (see SU_errno)
195   -2 : Read timed out (value defined in TimeOut parameter)
196   >0 : Total of bytes read
197 */
198 int SU_ReadTCPBuffer(SU_SOCKET sock,char *buf,int size,struct timeval *TimeOut,bool WaitForFullBuffer);
199 
200 SU_PServerInfo SU_CreateServer(int port,int type,bool ReUseAdrs);  /* Returns NULL on error */
201 int SU_ServerListen(SU_PServerInfo SI);                            /* SOCKET_ERROR on Error */
202 SU_PClientSocket SU_ServerAcceptConnection(SU_PServerInfo SI);     /* Returns NULL on error */
203 void SU_ServerDisconnect(SU_PServerInfo SI);
204 void SU_FreeSI(SU_PServerInfo SI); /* Disconnect and free SI */
205 SU_PClientSocket SU_ClientConnect(char *adrs,char *port,int type); /* Returns NULL on error */
206 int SU_ClientSend(SU_PClientSocket CS,char *msg);                  /* SOCKET_ERROR on Error */
207 int SU_ClientSendBuf(SU_PClientSocket CS,char *buf,int len);       /* SOCKET_ERROR on Error */
208 void SU_ClientDisconnect(SU_PClientSocket CS);
209 void SU_FreeCS(SU_PClientSocket CS); /* Disconnect and free CS */
210 int SU_UDPSendBroadcast(SU_PServerInfo SI,char *Text,int len,char *port);           /* SOCKET_ERROR on Error */
211 int SU_UDPSendToAddr(SU_PServerInfo SI,char *Text,int len,char *Addr,char *port);   /* SOCKET_ERROR on Error */
212 int SU_UDPSendToSin(SU_PServerInfo SI,char *Text,int len,struct sockaddr_in);       /* SOCKET_ERROR on Error */
213 int SU_UDPReceiveFrom(SU_PServerInfo SI,char *Text,int len,char **ip,int Blocking); /* SOCKET_ERROR on Error */
214 int SU_UDPReceiveFromSin(SU_PServerInfo SI,char *Text,int len,struct sockaddr_in *,int Blocking); /* SOCKET_ERROR on Error */
215 int SU_SetSocketOpt(SU_SOCKET sock,int Opt,int value); /* SOCKET_ERROR on Error */
216 bool SU_SockInit(int Major,int Minor); /* Inits Socks (MUST BE CALL BEFORE ANY OTHER FUNCTION) */
217 void SU_SockUninit(void); /* Uninits Socks (MUST BE CALL BEFORE EXITING) */
218 #ifdef _WIN32
219 #define SU_CLOSE_SOCKET(x) closesocket(x)
220 #define SU_EAGAIN WSAEWOULDBLOCK
221 #define SU_errno WSAGetLastError()
222 #define SU_ioctl ioctlsocket
223 #else /* !_WIN32 */
224 #define SU_CLOSE_SOCKET(x) close(x)
225 #define SU_EAGAIN EAGAIN
226 #define SU_errno errno
227 #define SU_ioctl ioctl
228 #endif /* _WIN32 */
229 #endif /* !SU_INCLUDE_NO_SOCKS */
230 
231 
232 /* **************************************** */
233 /*               String functions           */
234 /* **************************************** */
235 char *SU_strcat(char *dest,const char *src,size_t len); /* like strncat, but always NULL terminate dest */
236 char *SU_strcpy(char *dest,const char *src,size_t len); /* like strncpy, but doesn't pad with 0, and always NULL terminate dest */
237 int SU_snprintf(char *dest,size_t len, const char *format,...); /* like snprintf, but always NULL terminate dest - Returns -1 if string truncated */
238 char *SU_nocasestrstr(char *text, char *tofind);  /* like strstr(), but nocase */
239 bool SU_strwcmp(const char *s,const char *wild); /* True if wild equals s (wild may use '*') */
240 bool SU_nocasestrwcmp(const char *s,const char *wild); /* Same as strwcmp but without case */
241 bool SU_strwparse(const char *s,const char *wild,char buf[],int size,char *buf_ptrs[],int *ptrs_count); /* True if wild equals s (wild may use '*') */
242 bool SU_nocasestrwparse(const char *s,const char *wild,char buf[],int size,char *buf_ptrs[],int *ptrs_count); /* Same as nocasestrwparse but without case */
243 unsigned int SU_strnlen(const char *s,unsigned int max); /* Returns MAX(length of a string,max) (not including terminating null char) */
244 bool SU_ReadLine(FILE *fp,char S[],int len); /* Returns false on EOF */
245 bool SU_ParseConfig(FILE *fp,char Name[],int nsize,char Value[],int vsize); /* Returns false on EOF */
246 char *SU_TrimLeft(const char *S);
247 void SU_TrimRight(char *S);
248 char *SU_strparse(char *s,char delim); /* Like strtok, but if 2 consecutive delim are found, an empty string is returned (s[0] = 0) */
249 void SU_ExtractFileName(const char Path[],char FileName[],const int len); /* Extracts file name (with suffix) from path */
250 char *SU_strchrl(const char *s,const char *l,char *found); /* Searchs the first occurence of one char of l[i] in s, and returns it in found */
251 char *SU_strrchrl(const char *s,const char *l,char *found); /* Same as SU_strchrl but starting from the end of the string */
252 unsigned char SU_toupper(unsigned char c);
253 unsigned char SU_tolower(unsigned char c);
254 char *SU_strtoupper(char *s); /* s IS modified */
255 char *SU_strtolower(char *s); /* s IS modified */
256 bool SU_strcasecmp(const char *s,const char *p);
257 char *SU_strerror(int ErrorCode); /* Returns a static string which describes the error code (errno on linux, GetLastError on windows) */
258 
259 #ifdef _WIN32
260 #define strcasecmp _stricmp
261 #define strncasecmp _strnicmp
262 #define snprintf _snprintf
263 /* Set ISO C++ conformant names */
264 #define getpid _getpid
265 #define unlink _unlink
266 #define strdup _strdup
267 #define SU_strdup(x) ((x)==NULL)?NULL:_strdup(x)
268 #else /* !_WIN32 */
269 #define SU_strdup(x) ((x)==NULL)?NULL:strdup(x)
270 #endif /* _WIN32 */
271 
272 
273 /* **************************************** */
274 /*               Utils functions            */
275 /* **************************************** */
276 #ifndef FlagOn
277 #define FlagOn(x,f) ((x) & (f))
278 #endif /* !FlagOn */
279 #ifndef SetFlag
280 #define SetFlag(x,f) ((x) |= (f))
281 #endif /* !SetFlag */
282 #ifndef ClearFlag
283 #define ClearFlag(x,f) ((x) &= ~(f))
284 #endif /* !ClearFlag */
285 
286 FILE *SU_OpenLogFile(const char LogName[]);
287 void SU_CloseLogFile(FILE *fp);
288 void SU_WriteToLogFile(FILE *fp,const char Text[]);
289 /* Checks the http_proxy env var */
290 void SU_CheckProxyEnv(void);
291 /* Remove arguments for skyutils, and returns number of remaining arguments for main */
292 /* This function automatically calls SU_CheckProxyEnv if no proxy found in params */
293 int SU_GetSkyutilsParams(int argc,char *argv[]);
294 char *SU_LoadUserHeaderFile(const char FName[]);
295 char *SU_GetOptionsString(void);
296 #ifdef __unix__
297 bool SU_Daemonize(void);
298 bool SU_SetUserGroup(const char User[],const char Group[]); /* If User and/or Group is != NULL, setuid and setgid are used */
299 #endif /* __unix__ */
300 void SU_SetDebugLevel(const char AppName[],const int Level);
301 int SU_GetDebugLevel(void);
302 void SU_PrintSyslog(int Level,char *Txt, ...);
303 void SU_PrintDebug(int Level,char *Txt, ...);
304 #ifndef DEBUG
305 #ifdef __unix__
306 #define SU_PrintDebug(x,...) /* If you have an error here, remove 'x,...' from the () */
307 #include <syslog.h>
308 #define SU_SYSLOG_FN(x,y) syslog(x,y)
309 #else /* !__unix__ */
310 #define SU_PrintDebug() /* Avoid compilation warnings */
311 extern FILE *SU_LogFile;
312 #define SU_SYSLOG_FN(x,y) SU_WriteToLogFile(SU_LogFile,y)
313 #endif /* __unix__ */
314 #else /* DEBUG */
315 #define SU_SYSLOG_FN(x,y) printf(y)
316 #endif /* !DEBUG */
317 #ifdef _WIN32
318 #define SU_SLEEP(x) Sleep(x*1000)
319 #define SU_USLEEP(x) Sleep(x)
320 #else /* !_WIN32 */
321 #define SU_SLEEP(x) sleep(x)
322 #define SU_USLEEP(x) usleep(x*1000)
323 #endif /* _WIN32 */
324 #define SU_ANSI_BLACK  "0"
325 #define SU_ANSI_RED    "1"
326 #define SU_ANSI_GREEN  "2"
327 #define SU_ANSI_YELLOW "3"
328 #define SU_ANSI_BLUE   "4"
329 #define SU_ANSI_PINK   "5"
330 #define SU_ANSI_CYAN   "6"
331 #define SU_ANSI_WHITE  "7"
332 #if SU_ENABLE_ANSI_CODE
333 #define SU_ANSI_COLOR(f,b) "\033[3" f ";4" b "m"
334 #define SU_ANSI_BLINK      "\033[5m"
335 #define SU_ANSI_HIGHLIGHT  "\033[1m"
336 #define SU_ANSI_RESET      "\033[0m"
337 #else /* !SU_ENABLE_ANSI_CODE */
338 #define SU_ANSI_COLOR(f,b) ""
339 #define SU_ANSI_BLINK      ""
340 #define SU_ANSI_HIGHLIGHT  ""
341 #define SU_ANSI_RESET      ""
342 #endif /* SU_ENABLE_ANSI_CODE */
343 #ifdef _WIN32
344 typedef SU_u64 SU_TICKS;
345 #else /* !WIN32 */
346 typedef SU_u64 SU_TICKS;
347 #endif /* _WIN32 */
348 typedef SU_u32 SU_CPUSPEED;
349 SU_CPUSPEED SU_GetCPUSpeed(void);
350 void SU_GetTicks(SU_TICKS *tick); /* Returned value in processor ticks (Use SU_ElapsedTime to compute time in msec) */
351 SU_u32 SU_ElapsedTime(SU_TICKS t1,SU_TICKS t2,SU_CPUSPEED speed); /* Returned value in msec */
352 FILE *SU_fmemopen(void *buf,size_t size,const char *opentype);
353 void SU_FreeMemory(void *ptr); /* Frees any memory allocated by SkyUtils function */
354 double SU_GetTimeAsMilli(); /* Returns current time in milli-sec (since 1970) */
355 
356 /* **************************************** */
357 /*              Memory functions            */
358 /* **************************************** */
359 #ifndef SU_MALLOC_ALIGN_SIZE
360 #define SU_MALLOC_ALIGN_SIZE 16
361 #else /* SU_MALLOC_ALIGN_SIZE */
362 #if SU_MALLOC_ALIGN_SIZE < 8
363 #error "SU_MALLOC_ALIGN_SIZE must be strictly greater than 8"
364 #endif /* SU_MALLOC_ALIGN_SIZE < 8 */
365 #endif /* !SU_MALLOC_ALIGN_SIZE */
366 typedef void (SU_PRINT_FUNC)(bool Fatal,char *Txt, ...);
367 void SU_SetPrintFunc(SU_PRINT_FUNC *Func);
368 typedef void (SU_MEM_STATS_FUNC)(void *ptr,SU_u32 size,SU_u32 time,const char *file,SU_u32 line);
369 
370 void *SU_malloc(SU_u32 size); /* Allocates a bloc of memory aligned on SU_MALLOC_ALIGN_SIZE */
371 void *SU_calloc(SU_u32 nbelem,SU_u32 size); /* Allocates a bloc of memory aligned on SU_MALLOC_ALIGN_SIZE, and zeros it */
372 void *SU_realloc(void *memblock,SU_u32 size); /* Reallocates a bloc of memory aligned on SU_MALLOC_ALIGN_SIZE */
373 char *SU_strdup_memory(const char *in); /* Dups a string using a bloc of memory aligned on SU_MALLOC_ALIGN_SIZE */
374 void SU_free(void *memblock);   /* Frees a bloc previously allocated using SU_malloc */
375 #ifdef SU_MALLOC_TRACE
376 #undef calloc
377 #undef strdup
378 #define malloc(x) SU_malloc_trace(x,__FILE__,__LINE__)
379 #define calloc(x,y) SU_calloc_trace(x,y,__FILE__,__LINE__)
380 #define realloc(x,y) SU_realloc_trace(x,y,__FILE__,__LINE__)
381 #define strdup(x) SU_strdup_trace(x,__FILE__,__LINE__)
382 #define free(x) SU_free_trace(x,__FILE__,__LINE__)
383 #define trace_print SU_alloc_trace_print(true)
384 #define trace_print_count SU_alloc_trace_print(false)
385 #endif /* SU_MALLOC_TRACE */
386 void *SU_malloc_trace(SU_u32 size,char *file,SU_u32 line);
387 void *SU_calloc_trace(SU_u32 nbelem,SU_u32 size,char *file,SU_u32 line);
388 void *SU_realloc_trace(void *memblock,SU_u32 size,char *file,SU_u32 line);
389 char *SU_strdup_trace(const char *in,char *file,SU_u32 line);
390 void SU_free_trace(void *memblock,char *file,SU_u32 line);
391 void SU_alloc_trace_print(bool detail); /* Print all allocated blocks (if detail is true), and total number of chunks */
392 void SU_check_memory(void); /* Check memory heap */
393 void SU_alloc_stats(SU_MEM_STATS_FUNC *Func); /* Call Func for each chunk of memory */
394 SU_u32 SU_alloc_total_size(void); /* Returns the total size allocated */ /* Only available with SU_xx_trace functions */
395 /* MALLOC_CHECK_ environment variable :
396  *   0 : If a memory error occurs, execution silently goes on
397  *   1 : If a memory error occurs, a debug message is printed in stdout, and execution goes on
398  *   2 or not defined : If a memory error occurs, a debug message is printed in stdout, and abort is called
399 */
400 /* SU_MALLOC_TRACE environment variable :
401  *   0 or not defined : SU_free_trace does free trace of associated malloc
402  *   1 : SU_free_trace keep trace of associated malloc, and display more debug information if block already freed
403 */
404 /* SU_MALLOC_PRINT environment variable :
405  *   0 or not defined : Nothing happens
406  *   1 : SU_malloc_trace/SU_free_trace functions print memory bloc and file/line from where the function is called
407 */
408 
409 
410 /* **************************************** */
411 /*                 web functions            */
412 /* **************************************** */
413 #define ACT_GET    1
414 #define ACT_POST   2
415 #define ACT_PUT    3
416 #define ACT_DELETE 4
417 
418 #define URL_BUF_SIZE 2048
419 
420 typedef struct
421 {
422   int Code;
423   char *Location;
424 
425   char *Data;      /* NULL if no data */
426   int Data_Length; /* -1 if no data */
427   int Data_ToReceive;
428 } SU_TAnswer, *SU_PAnswer;
429 
430 struct SU_SHTTPActions;
431 
432 typedef struct
433 {
434   void (*OnSendingCommand)(struct SU_SHTTPActions *); /* User's CallBack just before sending request */
435   void (*OnAnswer)(SU_PAnswer,void *); /* User's CallBack just after answer received */
436   void (*OnOk)(SU_PAnswer,void *); /* User's CallBack for a 200 reply */
437   void (*OnCreated)(SU_PAnswer,void *); /* User's CallBack for a 201 reply */
438   void (*OnModified)(SU_PAnswer,void *); /* User's CallBack for a 202 reply */
439   void (*OnMoved)(SU_PAnswer,void *); /* User's CallBack for a 302 reply */
440   void (*OnForbidden)(SU_PAnswer,void *); /* User's CallBack for a 403 reply */
441   void (*OnNotFound)(SU_PAnswer,void *); /* User's CallBack for a 404 reply */
442   void (*OnTooBig)(SU_PAnswer,void *); /* User's CallBack for a 413 reply */
443   void (*OnUnknownHost)(SU_PAnswer,void *); /* User's CallBack for a 503 reply */
444   void (*OnOtherReply)(SU_PAnswer,int,void *); /* User's CallBack for all other replies */
445   void (*OnErrorSendingFile)(int,void *); /* User's CallBack for an error sending file (errno code passed) */
446 } SU_THTTP_CB, *SU_PHTTP_CB;
447 
448 typedef struct
449 {
450   char *Header; /* Header to send */
451   char *FileName; /* File to send (exclude Data) */
452   char *Data; /* Data to send (exclude FileName) */
453   int Length; /* Length of data */
454 } SU_THTTPPart, *SU_PHTTPPart;
455 
456 typedef struct SU_SHTTPActions
457 { /* Info to set BEFORE any call to ExecuteActions */
458   int  Command; /* ACT_xxx */
459   char URL[URL_BUF_SIZE];
460   char *URL_Params; /* ACT_GET & ACT_POST */
461   char *Post_Data;  /* ACT_POST */
462   int  Post_Length; /* ACT_POST */
463   char *ContentType; /* Content-type or use default */ /* ACT_GET & ACT_POST */
464   char *FileName;   /* ACT_PUT */ /* URL must contain the URL+New file name */ /* If defined for GET or POST, dump result to this file */
465   char *Referer;
466   SU_PList MultiParts; /* SU_PHTTPPart */ /* MultiParts, exclude Post_Data */ /* ACT_POST */
467   void *User;       /* User's info Passed to Callbacks */
468   int  Sleep;       /* Time to wait before sending command (sec) */
469   SU_THTTP_CB CB;   /* Callbacks structure */
470 
471   /* Info used internally */
472   char Host[100];
473   bool SSL;
474 } SU_THTTPActions, *SU_PHTTPActions;
475 
476 typedef struct
477 {
478   char *Name;
479   char *Value;
480   char *Domain;
481   char *Path;
482   char *Expire;
483   bool Secured;
484 } SU_TCookie, *SU_PCookie;
485 
486 typedef struct
487 {
488   char *Type;
489   char *Name;
490   char *Value;
491 } SU_TInput, *SU_PInput;
492 
493 typedef struct
494 {
495   char *Src;
496   char *Name;
497 } SU_TImage, *SU_PImage;
498 
499 typedef struct
500 {
501   char *Method;
502   char *Name;
503   char *Action;
504   SU_PList Inputs;
505 } SU_TForm, *SU_PForm;
506 
507 /* Sets the UserAgent string to send in every web request. Will not be used if SU_LoadUserHeaderFile() is used */
508 void SU_SetUserAgent(const char UA[]);
509 /* Sets proxy server,port, user and password values to be used by ExecuteActions (use NULL for proxy to remove use of the proxy) */
510 void SU_SetProxy(const char Proxy[],const int Port,const char User[], const char Password[]);
511 /* Sets the socket connection timeout (use 0 to reset default value) */
512 void SU_SetSocketTimeout(const int Timeout);
513 /* Returns 0 if ok, -1 if cannot connect to the host, -2 if a timeout occured */
514 int SU_ExecuteActions(SU_PList Actions);
515 void SU_FreeAction(SU_PHTTPActions Act);
516 
517 SU_PInput SU_GetInput(char *html);
518 SU_PInput SU_GetNextInput(void);
519 void SU_FreeInput(SU_PInput In);
520 
521 SU_PImage SU_GetImage(char *html);
522 SU_PImage SU_GetNextImage(void);
523 void SU_FreeImage(SU_PImage Im);
524 
525 void SU_FreeForm(SU_PForm Form);
526 
527 /* Retrieves the url (into a SU_PHTTPActions struct) of the 'link' from the 'Ans' page associated with the 'URL' request */
528 SU_PHTTPActions SU_RetrieveLink(const char URL[],const char Ans[],const char link[],const int index);
529 /* Retrieve link from a frameset */
530 SU_PHTTPActions SU_RetrieveFrame(const char URL[],const char Ans[],const char framename[]);
531 /* Retrieve document.forms[num] */
532 SU_PForm SU_RetrieveForm(const char Ans[],const int num);
533 
534 char *SU_AddLocationToUrl(const char *URL,const char *Host,const char *Location,bool ssl_mode);
535 
536 /* Encodes an URL */
537 char *SU_EncodeURL(const char URL_in[],char URL_out[],int URL_out_len);
538 
539 /* Skips white spaces before the string, then extracts it */
540 char *SU_GetStringFromHtml(const char Ans[],const char TextBefore[]);
541 
542 void SU_FreeCookie(SU_PCookie Cok);
543 extern SU_PList SW_Cookies; /* SU_PCookie */
544 
545 
546 /* **************************************** */
547 /*               Threads functions          */
548 /* **************************************** */
549 #ifndef SU_INCLUDE_NO_THREAD
550 #ifdef __unix__
551 #define SU_THREAD_HANDLE pthread_t
552 #define SU_THREAD_ROUTINE_TYPE(x) void *(*x)(void *)
553 #define SU_THREAD_ROUTINE(x,y) void * x(void *y)
554 #define SU_END_THREAD(x) pthread_exit(x)
555 #define SU_PROCESS_SELF (SU_u32)getpid()
556 #define SU_THREAD_SELF (SU_u32)(uintmax_t)pthread_self()
557 #define SU_THREAD_KEY_HANDLE pthread_key_t
558 #define SU_THREAD_ONCE_HANDLE pthread_once_t
559 #define SU_THREAD_ONCE_INIT PTHREAD_ONCE_INIT
560 #define SU_THREAD_ONCE(x,y) pthread_once(&x,y)
561 #define SU_THREAD_GET_SPECIFIC(x) pthread_getspecific(x)
562 #define SU_THREAD_SET_SPECIFIC(x,y) pthread_setspecific(x,y)
563 #define SU_THREAD_DESTROY_SPECIFIC(x,y)
564 #define SU_SEM_HANDLE sem_t
565 #define SU_SEM_WAIT(x) sem_wait(&(x))
566 #define SU_SEM_POST(x) sem_post(&(x))
567 #define SU_MUTEX_HANDLE pthread_mutex_t
568 #define SU_MUTEX_WAIT(x) pthread_mutex_lock(&(x))
569 #define SU_MUTEX_POST(x) pthread_mutex_unlock(&(x))
570 #define SU_CRITICAL pthread_mutex_t
571 #define SU_CRITICAL_ENTER(x) pthread_mutex_lock(&(x))
572 #define SU_CRITICAL_LEAVE(x) pthread_mutex_unlock(&(x))
573 #define SU_CRITICAL_TRY_AND_ENTER(x) (pthread_mutex_trylock(&(x)) == 0)
574 #else /* !__unix__ */
575 #define SU_THREAD_HANDLE unsigned long
576 #define SU_THREAD_ROUTINE_TYPE(x) void (__cdecl *x)(void *)
577 #define SU_THREAD_ROUTINE(x,y) void __cdecl x(void *y)
578 #define SU_END_THREAD(x) _endthread()
579 #define SU_PROCESS_SELF (SU_u32)GetCurrentProcessId()
580 #define SU_THREAD_SELF (SU_u32)GetCurrentThreadId()
581 #define SU_THREAD_KEY_HANDLE DWORD
582 #define SU_THREAD_ONCE_HANDLE DWORD
583 #define SU_THREAD_ONCE_INIT 0
584 #define SU_THREAD_ONCE(x,y) y()
585 #define SU_THREAD_GET_SPECIFIC(x) TlsGetValue(x)
586 #define SU_THREAD_SET_SPECIFIC(x,y) TlsSetValue(x,(LPVOID)y)
587 #define SU_THREAD_DESTROY_SPECIFIC(x,y) x(y)
588 #define SU_SEM_HANDLE HANDLE
589 #define SU_SEM_WAIT(x) WaitForSingleObject(x,INFINITE)
590 #define SU_SEM_POST(x) ReleaseSemaphore(x,1,NULL)
591 #define SU_MUTEX_HANDLE HANDLE
592 #define SU_MUTEX_WAIT(x) WaitForSingleObject(x,INFINITE)
593 #define SU_MUTEX_POST(x) ReleaseMutex(x)
594 #define SU_CRITICAL CRITICAL_SECTION
595 #define SU_CRITICAL_ENTER(x) EnterCriticalSection(&(x))
596 #define SU_CRITICAL_LEAVE(x) LeaveCriticalSection(&(x))
597 #define SU_CRITICAL_TRY_AND_ENTER(x) TryEnterCriticalSection(&(x))
598 #endif /* __unix__ */
599 /* Create a new thread */
600 bool SU_CreateThread(SU_THREAD_HANDLE *Handle,SU_THREAD_ROUTINE_TYPE(Entry),void *User,bool Detached); /* True on success */
601 /* Kill the specified thread */
602 void SU_KillThread(SU_THREAD_HANDLE Handle);
603 /* Terminate the specified thread */
604 void SU_TermThread(SU_THREAD_HANDLE Handle);
605 /* Suspend a thread */
606 void SU_SuspendThread(SU_THREAD_HANDLE Handle);
607 /* Resume a suspended thread */
608 void SU_ResumeThread(SU_THREAD_HANDLE Handle);
609 /* Create a new semaphore */
610 bool SU_CreateSem(SU_SEM_HANDLE *Handle,int InitialCount,int MaximumCount,const char SemName[]); /* True on success */
611 /* Free a semaphore */
612 bool SU_FreeSem(SU_SEM_HANDLE *Handle);
613 /* Create a new thread key */
614 bool SU_CreateThreadKey(SU_THREAD_KEY_HANDLE *Handle,SU_THREAD_ONCE_HANDLE *Once,void (*destroyts)(void *)); /* True on success */
615 /* Block all signals for the calling thread */
616 void SU_ThreadBlockSigs(void);
617 /* Create a new mutex */
618 bool SU_CreateMutex(SU_MUTEX_HANDLE *Handle,const char MutexName[]); /* True on success */
619 /* Free a mutex */
620 bool SU_FreeMutex(SU_MUTEX_HANDLE *Handle);
621 /* Create a critical section */
622 #define SU_CRITICAL_TYPE_ANY           1
623 #define SU_CRITICAL_TYPE_RECURSIVE     2
624 #define SU_CRITICAL_TYPE_NON_RECURSIVE 3
625 bool SU_CriticalInit(SU_CRITICAL *Crit,int Type); /* True on success */
626 /* Free a critical section */
627 bool SU_CriticalDelete(SU_CRITICAL *Crit);
628 #endif /* !SU_INCLUDE_NO_THREAD */
629 
630 
631 /* **************************************** */
632 /*           dynamic load functions         */
633 /* **************************************** */
634 #ifdef SU_USE_DL
635 #ifdef __unix__
636 #include <dlfcn.h>
637 #include <signal.h>
638 #define SU_DL_HANDLE void *
639 #define SU_DL_OPEN(x) dlopen(x,RTLD_LAZY)
640 #define SU_DL_CLOSE(x) dlclose(x)
641 #define SU_DL_SYM(x,y) dlsym(x,y)
642 #else /* !__unix__ */
643 #define SU_DL_HANDLE HINSTANCE
644 #define SU_DL_OPEN(x) LoadLibrary(x)
645 #define SU_DL_CLOSE(x) FreeLibrary(x)
646 #define SU_DL_SYM(x,y) GetProcAddress(x,y)
647 #endif /* __unix__ */
648 /* Loads the symbol "Name" from handle, but if not found, try with "_Name" */
649 void *SU_DL_GetSym(SU_DL_HANDLE handle, const char Name[]);
650 #endif /* SU_USE_DL */
651 
652 
653 /* **************************************** */
654 /*             Archive  functions           */
655 /* **************************************** */
656 #ifdef SU_USE_ARCH
657 
658 #define SU_ARCH_COMP_NONE 1
659 #define SU_ARCH_COMP_Z    2
660 #define SU_ARCH_COMP_BZ   4
661 
662 typedef struct
663 {
664   void *Data;        /* Resource data ('Size' bytes of data in this buffer) */
665   SU_u32 Size;       /* Size of the data pointer                            */
666   SU_u32 Stamp;      /* Time stamp of the original resource                 */
667 } SU_TRes, *SU_PRes;
668 
669 typedef struct
670 {
671   SU_u32 Offset;   /* Offset of data                   */
672   SU_u32 CompSize; /* Compressed size                  */
673   SU_u32 CompType; /* Compression type                 */
674   SU_u32 Reserved; /* Reserved for future use          */
675   SU_u32 OrigSize; /* Original size                    */
676   SU_u32 OrigTime; /* Original time stamp              */
677 
678   void   *Data;    /* Data pointer used when creating  */
679   bool   IsFile;   /* If Data represents a filename    */
680 } SU_TResHdr, *SU_PResHdr;
681 
682 typedef struct
683 {
684   FILE *fp;              /* Resource file              */
685   SU_TResHdr *Resources; /* Table of resources header  */
686   SU_u32 NbRes;          /* Number of resources        */
687   bool Flush;            /* Archive need to be flushed */
688 } SU_TArch, *SU_PArch;
689 
690 typedef unsigned int SU_AR_COMP_TYPE;
691 
692 /* *** Reading functions *** */
693 /* Opens a skyutils archive file (or a binary file [exe/dll] if the archive is selfcontained) */
694 SU_PArch SU_AR_OpenArchive(const char FileName[]);
695 /* Reads resource ResNum (0 is the first one) (NULL if failed) */
696 SU_PRes SU_AR_ReadRes(SU_PArch Arch,const SU_u32 ResNum,bool GetData);
697 /* Save resource ResNum to FileName (0 is the first one) (true on success) */
698 bool SU_AR_ReadResFile(SU_PArch Arch,const SU_u32 ResNum,const char FileName[]);
699 
700 
701 /* *** Writing functions *** */
702 /* Creates a new archive file. FileName can't be NULL */
703 SU_PArch SU_AR_CreateArchive(const char FileName[]);
704 /* Adds a resource to the archive (Data can be freed upon return) (true on success) */
705 bool SU_AR_AddRes(SU_PArch Arch,void *Data,SU_u32 Size,time_t Time,SU_AR_COMP_TYPE Type);
706 /* Adds a file resource to the archive (true on success) */
707 bool SU_AR_AddResFile(SU_PArch Arch,const char FileName[],SU_AR_COMP_TYPE Type);
708 
709 
710 /* *** Other functions *** */
711 /* Closes a previous opened/created archive (true on success) */
712 bool SU_AR_CloseArchive(SU_PArch Arch);
713 /* Frees a previous returned resource */
714 void SU_AR_FreeRes(SU_PRes Res);
715 /* Returns supported compression types (as a bit field) */
716 SU_AR_COMP_TYPE SU_AR_SupportedComps(void);
717 
718 #endif /* SU_USE_ARCH */
719 
720 
721 /* **************************************** */
722 /*             Registry functions           */
723 /* **************************************** */
724 #ifndef SU_INCLUDE_NO_REG
725 #ifdef _WIN32
726 #include <winreg.h>
727 #else /* !_WIN32 */
728 #define HKEY void *
729 #endif /* _WIN32 */
730 
731 #define SU_RB_ERR_SUCCESS            0
732 #define SU_RB_ERR_ACCESS_DENIED      1
733 #define SU_RB_ERR_WRONG_TYPE         2
734 #define SU_RB_ERR_INVALID_KEY        3
735 #define SU_RB_ERR_INVALID_PATH       4
736 #define SU_RB_ERR_LOCK_FAILED        5
737 #define SU_RB_ERR_PREMATURE_EOF      6
738 #define SU_RB_ERR_WRITE_ERROR        7
739 #define SU_RB_ERR_INVALID_TYPE       8
740 #define SU_RB_ERR_CORRUPTED          9
741 #define SU_RB_ERR_MORE_DATA         10
742 #define SU_RB_ERR_NO_SUCH_KEY       11
743 #define SU_RB_ERR_REGISTRY_NOT_OPEN 12
744 
745 int SU_RB_GetLastError();
746 
747 /* 'Key' parameter must be a succession of subkeys separated by '\', and finished by a keyname. To set/get the default value of a subkey, put a trailing '\' on 'Key' */
748 bool SU_RB_GetStrValue(const char Key[],char *buf,int buf_len,const char Default[]); /* True on success. Call SU_RB_GetLastError() for error */
749 bool SU_RB_GetStrLength(const char Key[],int *length); /* True on success. Call SU_RB_GetLastError() for error */
750 bool SU_RB_GetIntValue(const char Key[],int *Value,int Default); /* True on success. Call SU_RB_GetLastError() for error */
751 bool SU_RB_GetBinValue(const char Key[],char *buf,int buf_len,char *Default,int def_len); /* True on success. Call SU_RB_GetLastError() for error */
752 bool SU_RB_GetBinLength(const char Key[],int *length); /* True on success. Call SU_RB_GetLastError() for error */
753 bool SU_RB_SetStrValue(const char Key[],const char Value[]); /* True on success. Call SU_RB_GetLastError() for error */
754 bool SU_RB_SetIntValue(const char Key[],int Value); /* True on success. Call SU_RB_GetLastError() for error */
755 bool SU_RB_SetBinValue(const char Key[],const char *Value,int val_len); /* True on success. Call SU_RB_GetLastError() for error */
756 bool SU_RB_DelKey(const char Key[]); /* Recursively deletes All sub-keys and values of Key (and Key itself) */ /* True on success. Call SU_RB_GetLastError() for error */
757 bool SU_RB_DelValue(const char Key[]); /* True on success. Call SU_RB_GetLastError() for error */
758 
759 bool SU_RB_OpenRegistry(const char RegistryPath[]); /* Opens registry for reading/writing. True on success - Only one registry opened at one time, close previous one if opened */
760 bool SU_RB_CloseRegistry(void); /* Flush all writings since registry was opened and close it. True on success. If failed, nothing was flushed */
761 
762 HKEY SU_RB_OpenKeys(const char Key[],int Access); /* Opened HKEY or 0 on error */
763 HKEY SU_RB_CreateKeys(const char Key[]); /* Created HKEY or 0 on error */
764 bool SU_RB_EnumKey(HKEY Key,int Idx,char *Name,int name_len); /* True on Success. False when no more values available */
765 bool SU_RB_EnumStrValue(HKEY Key,int Idx,char *Name,int name_len,char *Value,int value_len); /* True on Success. False when no more values available */ /* All values must be of same type in the HKEY (int or string) */
766 bool SU_RB_EnumIntValue(HKEY Key,int Idx,char *Name,int name_len,int *Value); /* True on Success. False when no more values available */ /* All values must be of same type in the HKEY (int or string) */
767 void SU_RB_CloseKey(HKEY Key);
768 #endif /* !SU_INCLUDE_NO_REG */
769 
770 
771 /* **************************************** */
772 /*              Debug  functions            */
773 /* **************************************** */
774 #define SU_DBG_OUTPUT_NONE    0
775 #define SU_DBG_OUTPUT_PRINTF  1
776 #define SU_DBG_OUTPUT_CONSOLE 2
777 #define SU_DBG_OUTPUT_FILE    4
778 #define SU_DBG_OUTPUT_SOCKET  8
779 #define SU_DBG_OUTPUT_POPUP   16
780 
781 #define SU_DBG_CONSOLE_DEFAULT_WINDOW_NAME "SkyUtils_Debug_Window"
782 
783 /* ** Global options */
784 void SU_DBG_SetFlags(const SU_u64 Flags); /* Effective immediatly */
785 void SU_DBG_SetOutput(const SU_u16 Output); /* Effective immediatly */
786 /* If PrintTime is set to true, date/time is also printed. CurrentProcessId/CurrentThreadId is printed if PrintProcessId/PrintThreadId is set to true */
787 void SU_DBG_SetOptions(const bool PrintTime,const bool PrintProcessId,const bool PrintThreadId); /* Effective immediatly */
788 
789 /* ** Printf Output Options ** */
790 /* Ansi color is used if AnsiColor is set to true */
791 void SU_DBG_OUT_PRINTF_SetOptions(const bool AnsiColor); /* Effective immediatly */
792 /* ** Console Output Options ** */
793 /* WindowName is the name of the debug console window. Set it to NULL to stop sending messages to it */
794 void SU_DBG_OUT_CONSOLE_SetOptions(const char WindowName[]); /* Effective immediatly (changes the Console immediatly) */
795 /* ** File Output Options ** */
796 /* FileName is the name of the log file. Set it to NULL to close log file. File is deleted if DeletePreviousLog is set to true */
797 void SU_DBG_OUT_FILE_SetOptions(const char FileName[],bool DeletePreviousLog); /* Effective immediatly (closes old file if any, opens the new one) */
798 /* ** Socket Output Options ** */
799 /* HostName:Port is the Host and port to connect to. Set Port to 0, to remove this host from list of socket */
800 void SU_DBG_OUT_SOCKET_SetOptions(const char HostName[],const int Port); /* Effective immediatly (adds a new socket) */
801 
802 /* PrintDebug fonction. \n is added a the end of the string */
803 void SU_DBG_PrintDebug(const SU_u64 Type,char *Txt, ...);
804 
805 /* **** Debug Env vars **** */
806 #define SU_DBG_HELP_MESSAGE "SkyUtils Debug : Environment variables HELP (overrides application init on the first 'SU_DBG_PrintDebug' call) :\n\n" \
807 "   Global env var : SU_DBG_HELP = Print this help\n" \
808 "                    SU_DBG_OUTPUT = {printf,console,file,socket,popup} (space separated)\n" \
809 "                    SU_DBG_FLAGS = <Flags> (Flags is a 64bits bitfield defining which flags to output)\n" \
810 "                    SU_DBG_OPTIONS = {time,process,thread} (space separated)\n" \
811 "    printf env var : SU_DBG_OUT_PRINTF = {0|1} (AnsiColor boolean)\n" \
812 "    console env var : SU_DBG_OUT_CONSOLE = <WindowName>\n" \
813 "    file env var : SU_DBG_OUT_FILE = {0|1} <FileName> (0|1 is DeletePreviousLog boolean)\n" \
814 "    socket env var : SU_DBG_OUT_SOCKET = <HostName:Port>[ <HostName:Port>] ...\n" \
815 "    popup env var : N/A\n" \
816 "\n"
817 
818 #ifdef _WIN32
819 /* Special Windows Config Function (pops up a GUI to choose debug options, overriding application init, and env vars) - Returns true if debug options were changed */
820 /* hInstance must be the Instance of the module who is linked with the skyutils library (use GetModuleHandle(NULL) to retrieve calling process' HINSTANCE) */
821 bool SU_DBG_ChooseDebugOptions_Windows(HINSTANCE hInstance,HWND Parent);
822 #endif /* _WIN32 */
823 
824 
825 
826 /* **************************************** */
827 /*              MISC   functions            */
828 /* **************************************** */
829 
830 /* Dummy functions used by configure, to check correct version of skyutils */
831 /* Remove old ones if compatibility has been broken */
832 void SU_Dummy208(void);
833 void SU_Dummy209(void);
834 
835 
836 #if defined(__cplusplus) && !defined(__BORLANDC__)
837 }
838 #endif /* __cplusplus */
839 
840 #endif /* !__SKY_UTILS_H__ */
841