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;
41 n = tokenizebyseparator(data, "\n");
42 e.url_rbuf = buf_create();
45 print("url_URI_Get_Callback: out of memory in buf_create\n");
46 e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
54 print("url_URI_Get_Callback: out of memory in buf_create\n");
55 e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
60 for(i = 0; i < n; ++i)
61 bufstr_set(e.url_rbuf, i, argv(i));
62 e.url_ready(e, e.url_ready_pass, URL_READY_CANREAD);
68 e.url_ready(e, e.url_ready_pass, -status);
75 void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
79 if(strstrofs(url, "://", 0) >= 0)
85 // collect data to a stringbuffer for a POST request
86 // attempts to close will result in a reading handle
88 // create a writing end that does nothing yet
90 e.classname = "url_fopen_file";
91 e.url_url = strzone(url);
93 e.url_wbuf = buf_create();
96 print("url_fopen: out of memory in buf_create\n");
97 rdy(e, pass, URL_READY_ERROR);
104 rdy(e, pass, URL_READY_CANWRITE);
110 // get slot for HTTP request
111 for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i)
112 if(url_fromid[i] == world)
116 for(i = 0; i < autocvar__urllib_nextslot; ++i)
117 if(url_fromid[i] == world)
119 if(i >= autocvar__urllib_nextslot)
121 print("url_fopen: too many concurrent requests\n");
122 rdy(world, pass, URL_READY_ERROR);
128 if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0))
130 print("url_fopen: failure in crypto_uri_postbuf\n");
131 rdy(world, pass, URL_READY_ERROR);
135 // Make a dummy handle object (no buffers at
136 // all). Wait for data to come from the
137 // server, then call the callback
139 e.classname = "url_fopen_file";
140 e.url_url = strzone(url);
145 e.url_ready_pass = pass;
149 // make sure this slot won't be reused quickly even on map change
150 cvar_set("_urllib_nextslot", ftos(mod(i + 1, NUM_URL_ID)));
157 fh = fopen(url, mode);
160 rdy(world, pass, URL_READY_ERROR);
166 e.classname = "url_fopen_file";
168 if(mode == FILE_READ)
169 rdy(e, pass, URL_READY_CANREAD);
171 rdy(e, pass, URL_READY_CANWRITE);
177 void url_fclose(entity e, url_ready_func rdy, entity pass)
186 // we are closing the write end (HTTP POST request)
188 // get slot for HTTP request
189 for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i)
190 if(url_fromid[i] == world)
194 for(i = 0; i < autocvar__urllib_nextslot; ++i)
195 if(url_fromid[i] == world)
197 if(i >= autocvar__urllib_nextslot)
199 print("url_fclose: too many concurrent requests\n");
200 rdy(e, pass, URL_READY_ERROR);
202 strunzone(e.url_url);
209 if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0))
211 print("url_fclose: failure in crypto_uri_postbuf\n");
212 rdy(e, pass, URL_READY_ERROR);
214 strunzone(e.url_url);
219 // delete write end. File handle is now in unusable
220 // state. Wait for data to come from the server, then
225 e.url_ready_pass = pass;
229 // make sure this slot won't be reused quickly even on map change
230 cvar_set("_urllib_nextslot", ftos(mod(i + 1, NUM_URL_ID)));
234 // we have READ all data, just close
235 rdy(e, pass, URL_READY_CLOSED);
237 strunzone(e.url_url);
245 rdy(e, pass, URL_READY_CLOSED); // closing creates no reading handle
250 // with \n (blame FRIK_FILE)
251 string url_fgets(entity e)
257 s = bufstr_get(e.url_rbuf, e.url_rbufpos);
264 return fgets(e.url_fh);
268 // without \n (blame FRIK_FILE)
269 void url_fputs(entity e, string s)
274 bufstr_set(e.url_wbuf, e.url_wbufpos, s);