]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/urllib.qc
add urllib (not used yet)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / urllib.qc
1 // files (-1 for URL)
2 .float url_fh;
3
4 // URLs
5 .string url_url;
6 .float url_wbuf;
7 .float url_wbufpos;
8 .float url_rbuf;
9 .float url_rbufpos;
10 .float url_id;
11 .url_ready_func url_ready;
12 .entity url_ready_pass;
13
14 #define MIN_URL_ID 128
15 #define NUM_URL_ID 64
16 entity url_fromid[NUM_URL_ID];
17
18 void url_URI_Get_Callback(float id, float status, string data)
19 {
20         if(id < MIN_URL_ID)
21                 return 0;
22         id -= MIN_URL_ID;
23         if(id >= NUM_URL_ID)
24                 return 0;
25         entity e;
26         e = url_fromid(id);
27         if(!e)
28                 return 0;
29         if(e.url_rbuf >= 0)
30         {
31                 print(sprintf("WARNING: handle %d (%s) has already received data?!?\n", id + NUM_URL_ID, e.url_url));
32                 return 0;
33         }
34
35         if(status == 0)
36         {
37                 // WE GOT DATA!
38                 float n, i;
39                 n = tokenizebyseparator(data, "\n");
40                 e.url_rbuf = buf_create();
41                 e.url_rbufpos = 0;
42                 if(e.url_rbuf < 0)
43                 {
44                         backtrace("buf_create: out of memory");
45                         e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
46                         strunzone(e.url_url);
47                         remove(e);
48                 }
49                 for(i = 0; i < n; ++i)
50                         bufstr_set(e.url_rbuf, i, argv(i));
51                 e.url_ready(e, e.url_ready_pass, URL_READY_CANREAD);
52                 return 1;
53         }
54         else
55         {
56                 // an ERROR
57                 e.url_ready(e, e.url_ready_pass, -status);
58                 strunzone(e.url_url);
59                 remove(e);
60                 return 1;
61         }
62 }
63
64 void url_fopen(string url, float mode, entity pass, url_ready_func ready)
65 {
66         entity e;
67         float i;
68         if(strstrofs(url, "://", -1))
69         {
70                 switch(mode)
71                 {
72                         case FILE_WRITE:
73                         case FILE_APPEND:
74                                 // collect data to a stringbuffer for a POST request
75                                 // attempts to close will result in a reading handle
76                                 e = spawn();
77                                 e.classname = "url_fopen_file";
78                                 e.url_url = strzone(url);
79                                 e.url_fh = -1;
80                                 e.url_wbuf = buf_create();
81                                 if(e.url_wbuf < 0)
82                                 {
83                                         backtrace("buf_create: out of memory");
84                                         strunzone(e.url_url);
85                                         remove(e);
86                                         ready(world, pass, URL_READY_ERROR);
87                                         return;
88                                 }
89                                 e.url_wbufpos = 0;
90                                 e.url_rbuf = -1;
91                                 ready(e, pass, URL_READY_CANWRITE);
92                                 break;
93
94                         case FILE_READ:
95                                 // read data only
96                                 for(i = 0; i < NUM_URL_ID; ++i)
97                                         if(url_fromid[i] == world)
98                                                 break;
99                                 if(i >= NUM_URL_ID)
100                                         return -1;
101
102                                 e = spawn();
103                                 e.classname = "url_fopen_file";
104                                 e.url_url = strzone(url);
105                                 e.url_fh = -1;
106                                 e.url_rbuf = -1;
107                                 e.url_wbuf = -1;
108                                 e.url_id = i;
109                                 if(!uri_get(uri, e.url_id + MIN_URL_ID))
110                                 {
111                                         backtrace("uri_get: failed");
112                                         strunzone(e.url_url);
113                                         remove(e);
114                                         ready(world, pass, URL_READY_ERROR);
115                                         return;
116                                 }
117                                 e.url_ready = ready;
118                                 e.url_ready_pass = pass;
119                                 break;
120                 }
121         }
122         else
123         {
124                 float fh;
125                 fh = fopen(url, mode);
126                 if(fh < 0)
127                         return -1;
128                 else
129                 {
130                         e = spawn();
131                         e.classname = "url_fopen_file";
132                         e.url_fh = fh;
133                         if(mode == FILE_READ)
134                                 ready(e, pass, URL_READY_CANREAD);
135                         else
136                                 ready(e, pass, URL_READY_CANWRITE);
137                 }
138         }
139 }
140
141 void url_fclose(entity e, entity pass, url_ready_func ready)
142 {
143         float i;
144
145         if(e.url_fh < 0)
146         {
147                 if(e.url_wbuf >= 0)
148                 {
149                         for(i = 0; i < NUM_URL_ID; ++i)
150                                 if(url_fromid[i] == world)
151                                         break;
152                         if(i >= NUM_URL_ID)
153                         {
154                                 ready(e, pass, URL_READY_ERROR);
155                                 buf_del(e.url_wbuf);
156                                 strunzone(e.url_url);
157                                 remove(e);
158                                 return;
159                         }
160
161                         if(!uri_postbuf(uri, e.url_id + MIN_URL_ID, "text/plain", "\n", e.url_wbuf))
162                         {
163                                 ready(e, pass, URL_READY_ERROR);
164                                 buf_del(e.url_wbuf);
165                                 strunzone(e.url_url);
166                                 remove(e);
167                                 return;
168                         }
169
170                         buf_del(e.url_wbuf);
171                         e.url_wbuf = -1;
172                         e.url_ready = ready;
173                         e.url_ready_pass = pass;
174                 }
175                 else
176                 {
177                         // we have READ all data
178                         ready(e, pass, URL_READY_CLOSED);
179                         buf_del(e.url_rbuf);
180                         strunzone(e.url_url);
181                         remove(e);
182                 }
183         }
184         else
185         {
186                 // file
187                 fclose(e.url_fh);
188                 ready(e, pass, URL_READY_CLOSED); // closing creates no reading handle
189                 remove(e);
190         }
191 }
192
193 // with \n
194 string url_fgets(entity e)
195 {
196         if(e.url_fh < 0)
197         {
198                 // curl
199                 string s;
200                 s = bufstr_get(e.url_rbuf, e.url_rbufpos);
201                 ++e.url_rbufpos;
202                 return s;
203         }
204         else
205         {
206                 // file
207                 return fgets(e.url_fh);
208         }
209 }
210
211 // without \n
212 void url_fputs(entity e, string s)
213 {
214         if(e.url_fh < 0)
215         {
216                 // curl
217                 bufstr_set(e.url_wbuf, e.url_wbufpos, s);
218                 ++e.url_wbufpos;
219         }
220         else
221         {
222                 // file
223                 fputs(e, s);
224         }
225 }