11 .url_ready_func url_ready;
12 .entity url_ready_pass;
14 entity url_fromid[NUM_URL_ID];
15 float autocvar__urllib_nextslot;
17 float url_URI_Get_Callback(float id, float status, string data)
28 if(e.url_rbuf >= 0 || e.url_wbuf >= 0)
30 print(sprintf("WARNING: handle %d (%s) has already received data?!?\n", id + NUM_URL_ID, e.url_url));
34 // whatever happens, we will remove the URL from the list of IDs
35 url_fromid[id] = world;
37 // if we get here, we MUST have both buffers cleared
38 if(e.url_rbuf != -1 || e.url_wbuf != -1 || e.url_fh != -1)
39 error("url_URI_Get_Callback: not a request waiting for data");
45 n = tokenizebyseparator(data, "\n");
46 e.url_rbuf = buf_create();
49 print("url_URI_Get_Callback: out of memory in buf_create\n");
50 e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
58 print("url_URI_Get_Callback: out of memory in buf_create\n");
59 e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
64 for(i = 0; i < n; ++i)
65 bufstr_set(e.url_rbuf, i, argv(i));
66 e.url_ready(e, e.url_ready_pass, URL_READY_CANREAD);
72 e.url_ready(e, e.url_ready_pass, -fabs(status));
79 void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
83 if(strstrofs(url, "://", 0) >= 0)
89 // collect data to a stringbuffer for a POST request
90 // attempts to close will result in a reading handle
92 // create a writing end that does nothing yet
94 e.classname = "url_fopen_file";
95 e.url_url = strzone(url);
97 e.url_wbuf = buf_create();
100 print("url_fopen: out of memory in buf_create\n");
101 rdy(e, pass, URL_READY_ERROR);
102 strunzone(e.url_url);
108 rdy(e, pass, URL_READY_CANWRITE);
114 // get slot for HTTP request
115 for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i)
116 if(url_fromid[i] == world)
120 for(i = 0; i < autocvar__urllib_nextslot; ++i)
121 if(url_fromid[i] == world)
123 if(i >= autocvar__urllib_nextslot)
125 print("url_fopen: too many concurrent requests\n");
126 rdy(world, pass, URL_READY_ERROR);
132 if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0))
134 print("url_fopen: failure in crypto_uri_postbuf\n");
135 rdy(world, pass, URL_READY_ERROR);
139 // Make a dummy handle object (no buffers at
140 // all). Wait for data to come from the
141 // server, then call the callback
143 e.classname = "url_fopen_file";
144 e.url_url = strzone(url);
149 e.url_ready_pass = pass;
153 // make sure this slot won't be reused quickly even on map change
154 cvar_set("_urllib_nextslot", ftos(mod(i + 1, NUM_URL_ID)));
161 fh = fopen(url, mode);
164 rdy(world, pass, URL_READY_ERROR);
170 e.classname = "url_fopen_file";
172 if(mode == FILE_READ)
173 rdy(e, pass, URL_READY_CANREAD);
175 rdy(e, pass, URL_READY_CANWRITE);
181 void url_fclose(entity e, url_ready_func rdy, entity pass)
187 if(e.url_rbuf == -1 || e.url_wbuf != -1) // not(post GET/POST request)
188 if(e.url_rbuf != -1 || e.url_wbuf == -1) // not(pre POST request)
189 error("url_fclose: not closable in current state");
194 // we are closing the write end (HTTP POST request)
196 // get slot for HTTP request
197 for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i)
198 if(url_fromid[i] == world)
202 for(i = 0; i < autocvar__urllib_nextslot; ++i)
203 if(url_fromid[i] == world)
205 if(i >= autocvar__urllib_nextslot)
207 print("url_fclose: too many concurrent requests\n");
208 rdy(e, pass, URL_READY_ERROR);
210 strunzone(e.url_url);
217 if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0))
219 print("url_fclose: failure in crypto_uri_postbuf\n");
220 rdy(e, pass, URL_READY_ERROR);
222 strunzone(e.url_url);
227 // delete write end. File handle is now in unusable
228 // state. Wait for data to come from the server, then
233 e.url_ready_pass = pass;
237 // make sure this slot won't be reused quickly even on map change
238 cvar_set("_urllib_nextslot", ftos(mod(i + 1, NUM_URL_ID)));
242 // we have READ all data, just close
243 rdy(e, pass, URL_READY_CLOSED);
245 strunzone(e.url_url);
253 rdy(e, pass, URL_READY_CLOSED); // closing creates no reading handle
258 // with \n (blame FRIK_FILE)
259 string url_fgets(entity e)
264 error("url_fgets: not readable in current state");
267 s = bufstr_get(e.url_rbuf, e.url_rbufpos);
274 return fgets(e.url_fh);
278 // without \n (blame FRIK_FILE)
279 void url_fputs(entity e, string s)
284 error("url_fputs: not writable in current state");
286 bufstr_set(e.url_wbuf, e.url_wbufpos, s);