93d3b564519b56bd0e3b1dd7eb617017ddc3ba39
[tpg/acess2.git] / Usermode / Libraries / liburi.so_src / main.c
1 /*
2  * Acess2 - URI Parser and opener
3  * By John Hodge (thePowersGang)
4  */
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <uri.h>
10
11 // === STRUCTURES ===
12 struct sURIFile
13 {
14         void    *Handle;
15          int    Mode;
16         tURIHandler     *Handler;
17          int    CurBlockOffset;
18         char    Buffer[];
19 };
20
21 // === PROTOTYPES ===
22  int    SoMain(void);
23 tURI    *URI_Parse(const char *String);
24 tURIFile        *URI_MakeHandle(int Mode, void *Handle, tURIHandler *Handler);
25 tURIFile        *URI_Open(int Mode, tURI *URI);
26 size_t  URI_Read(tURIFile *File, size_t Bytes, void *Buffer);
27 size_t  URI_Write(tURIFile *File, size_t Bytes, void *Buffer);
28 void    URI_Close(tURIFile *File);
29 // --- file:/// handler
30 void    *URI_file_Open(const char *Host, int Port, const char *Path, int Mode);
31 void    URI_file_Close(void *Handle);
32 size_t  URI_file_Read(void *Handle, size_t Bytes, void *Buffer);
33 size_t  URI_file_Write(void *Handle, size_t Bytes, const void *Buffer);
34 off_t   URI_file_GetSize(void *Handle);
35
36 // === CONSTANTS ===
37 // Builtin URI protocol handlers
38 tURIHandler     caBuiltinHandlers[] = {
39         {"file", 0,
40                 URI_file_Open, URI_file_Close,
41                 URI_file_Read, URI_file_Write,
42                 URI_file_GetSize
43         }
44 };
45 #define NUM_BUILTIN_HANDLERS    (sizeof(caBuiltinHandlers)/sizeof(caBuiltinHandlers[0]))
46
47 // === CODE ===
48 int SoMain(void)
49 {
50         return 0;
51 }
52
53 tURI *URI_Parse(const char *String)
54 {
55         const char      *tmp = String;
56         tURI    *ret;
57          int    protolen;
58         
59         if(!String)     return NULL;
60         
61         protolen = 0;
62         while( isalpha(*tmp) || isdigit(*tmp) ) tmp++, protolen++;
63         
64         // true URI
65         if(tmp[0] == ':' && tmp[1] == '/' && tmp[2] == '/')
66         {
67                  int    hostlen, portlen, pathlen;
68                 tmp += 3;       // Eat '://'
69                 ret = malloc(sizeof(tURI) + protolen + 1 + strlen(tmp) + 1);
70                 
71                 ret->Proto = (char*)ret + sizeof(tURI);
72                 memcpy(ret->Proto, String, protolen);
73                 ret->Proto[protolen] = '\0';
74                 
75                 ret->Host = ret->Proto + protolen + 1;
76                 hostlen = 0;
77                 
78                 // IPv6
79                 if( *tmp == '[' )
80                 {
81                         tmp ++;
82                         while( *tmp && *tmp != ']' ) {
83                                 ret->Host[hostlen] = *tmp;
84                                 tmp ++;
85                                 hostlen ++;
86                         }
87                         tmp ++;
88                         ret->Host[hostlen] = '\0';
89                 }
90                 // IPv4/DNS
91                 else
92                 {
93                         while( *tmp && *tmp != '/' && *tmp != ':' )
94                         {
95                                 ret->Host[hostlen] = *tmp;
96                                 tmp ++;
97                                 hostlen ++;
98                         }
99                         ret->Host[hostlen] = '\0';
100                 }
101                 
102                 // Port
103                 if( *tmp == ':' ) {
104                         ret->PortStr = ret->Host + hostlen + 1;
105                         tmp ++;
106                         portlen = 0;
107                         while(isalpha(*tmp) || isdigit(*tmp))
108                         {
109                                 ret->PortStr[portlen] = *tmp;
110                                 portlen ++;
111                                 tmp ++;
112                         }
113                         ret->PortStr[portlen] = '\0';
114                         
115                         ret->PortNum = atoi(ret->PortStr);
116                         if(!ret->PortNum && !(ret->PortStr[0] == '0' && portlen == 1) )
117                         {
118                                 // error!
119                                 ret->Path = NULL;
120                                 return ret;
121                         }
122                 }
123                 else {
124                         ret->PortStr = NULL;
125                         ret->PortNum = -1;
126                         portlen = 0;
127                 }
128                 
129                 if(*tmp == '\0')
130                 {
131                         ret->Path = NULL;
132                         return ret;
133                 }
134                 
135                 // TODO: What to do on a parse error
136                 if(*tmp != '/') {
137                         ret->Path = NULL;
138                         return ret;
139                 }
140                 
141                 if(ret->PortStr)
142                         ret->Path = ret->PortStr + portlen + 1;
143                 else
144                         ret->Path = ret->Host + hostlen + 1;
145                 
146                 pathlen = 0;
147                 strcpy(ret->Path, tmp);
148                 
149                 return ret;
150         }
151         else
152         {
153 //              char    *cwd;
154 //               int    retlen;
155                 
156                 // Path
157                 // TODO: What to do?
158                 // Probably return file:///<path>
159                 // but should I get the CWD and use append that?
160                 ret = malloc( sizeof(tURI) + strlen(String) + 1 );
161                 ret->Path = (char*)ret + sizeof(tURI);
162                 strcpy(ret->Path, String);
163                 ret->Proto = "file";
164                 ret->Host = NULL;
165                 ret->PortNum = 0;
166                 ret->PortStr = NULL;
167                 return ret;
168         }
169 }
170
171 tURIFile *URI_MakeHandle(int Mode, void *Handle, tURIHandler *Handler)
172 {
173         tURIFile        *ret;
174         
175         ret = malloc(sizeof(tURIFile)+Handler->BlockSize);
176         if(!ret)        return NULL;
177         
178         ret->Handle = Handle;
179         ret->Mode = Mode;
180         ret->Handler = Handler;
181         ret->CurBlockOffset = 0;
182         
183         return ret;
184 }
185
186 tURIFile *URI_Open(int Mode, tURI *URI)
187 {
188         tURIHandler     *handler;
189         tURIFile        *ret;
190         void    *handle;
191          int    i;
192         
193         if(!URI)
194                 return NULL;
195         
196         for( i = 0; i < NUM_BUILTIN_HANDLERS; i ++ )
197         {
198                 if(strcmp(URI->Proto, caBuiltinHandlers[i].Name) == 0)
199                         break;
200         }
201         
202         if( i == NUM_BUILTIN_HANDLERS )
203         {
204                 // TODO: Dynamics
205                 printf("URI_Open: Warning - Unknown URI handler\n");
206                 return NULL;
207         }
208         else
209                 handler = &caBuiltinHandlers[i];
210         
211         printf("URI_Open: handler->Open = %p\n", handler->Open);
212         
213         handle = handler->Open(URI->Host, URI->PortNum, URI->Path, Mode);
214         printf("URI_Open: handle = %i\n", handle);
215         if(handle == NULL)      return NULL;
216         
217         printf("URI_MakeHandle(Mode=%i, handle=%i, handler=%p)\n",
218                 Mode, handle, handler);
219         ret = URI_MakeHandle(Mode, handle, handler);
220         if(!ret) {
221                 handler->Close( handle );
222                 return NULL;
223         }
224         return ret;
225 }
226
227 int URI_GetSize(tURIFile *File, size_t *Size)
228 {
229         if( !File || !Size )    return -1;
230         
231         if( File->Handler->GetSize )
232         {
233                 *Size = File->Handler->GetSize(File->Handle);
234                 return 0;       // Success
235         }
236         
237         return 1;       // Size not avaliable
238 }
239
240 /**
241  * \brief Read from a URI file
242  */
243 size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer)
244 {
245         size_t  rem = Bytes;
246         void    *buf = Buffer;
247         size_t  tmp;
248         
249         printf("URI_Read(File=%p, Bytes=%u, Buffer=%p)\n",
250                 File, (unsigned int)Bytes, Buffer);
251         
252         if(!File || !Buffer)    return -1;
253         if(Bytes == 0)  return 0;
254         
255         if( !(File->Mode & URI_MODE_READ) )     return -1;
256         
257         // Read from cache if avaliable
258         if(File->Handler->BlockSize && File->CurBlockOffset)
259         {
260                  int    avail;
261                 
262                 avail = File->Handler->BlockSize - File->CurBlockOffset;
263                 
264                 if(avail >= Bytes) {
265                         memcpy(Buffer, File->Buffer, Bytes);
266                         File->CurBlockOffset += Bytes;
267                         File->CurBlockOffset %= File->Handler->BlockSize;
268                         return Bytes;
269                 }
270                 
271                 rem -= avail;
272                 memcpy(Buffer, File->Buffer, avail);
273                 File->CurBlockOffset = 0;
274                 buf += avail;
275         }
276         
277         
278         if( File->Handler->BlockSize )
279         {
280                 // Read whole blocks
281                 while( rem >= File->Handler->BlockSize )
282                 {
283                         tmp = File->Handler->Read( File->Handle, File->Handler->BlockSize, buf );
284                         if(tmp < File->Handler->BlockSize)
285                                 return Bytes - rem - tmp;
286                         buf += File->Handler->BlockSize;
287                 }
288                 
289                 // Read the trailing part
290                 if(rem)
291                 {
292                         File->Handler->Read( File->Handle, File->Handler->BlockSize, File->Buffer );
293                         memcpy( buf, File->Buffer, rem );
294                         File->CurBlockOffset += rem;
295                 }
296                 return Bytes;
297         }
298         
299         return File->Handler->Read( File->Handle, Bytes, Buffer );
300 }
301
302 /**
303  * \brief Write to a URI file
304  */
305
306
307 // ====
308 // Builtin Handlers
309 // ====
310 void *URI_file_Open(const char *Host, int Port, const char *Path, int Mode)
311 {
312         const char      *smode = NULL;
313         if( (Mode & URI_MODE_READ) && (Mode & URI_MODE_WRITE))
314                 smode = "r+";
315         else if( (Mode & URI_MODE_READ) )
316                 smode = "r";
317         else if( (Mode & URI_MODE_WRITE) )
318                 smode = "w";
319         else
320                 smode = "";
321         
322 //      printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
323         return fopen(Path, smode);
324 }
325 size_t URI_file_Read(void *Handle, size_t Bytes, void *Buffer)
326 {
327 //      printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
328 //              Handle, Buffer, (int)Bytes);
329         return fread(Buffer, Bytes, 1, Handle);
330 }
331 size_t URI_file_Write(void *Handle, size_t Bytes, const void *Buffer)
332 {
333         return fwrite(Buffer, Bytes, 1, Handle);
334 }
335 void URI_file_Close(void *Handle)
336 {
337         fclose(Handle);
338 }
339 off_t URI_file_GetSize(void *Handle)
340 {
341         off_t curpos = ftell(Handle);
342         off_t ret;
343         fseek(Handle, 0, SEEK_END);
344         ret = ftell(Handle);
345         fseek(Handle, curpos, SEEK_SET);
346         return ret;
347 }
348

UCC git Repository :: git.ucc.asn.au