blob: b55c388ffc3fed48c49c11ee0a9a8939b087b288 [file] [log] [blame]
adamdunkels14fb5fc2003-08-20 22:36:44 +00001/*
2 * Copyright (c) 2002, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
adamdunkels16a7b262004-07-04 21:15:53 +000014 * 3. The name of the author may not be used to endorse or promote
adamdunkels14fb5fc2003-08-20 22:36:44 +000015 * products derived from this software without specific prior
16 * written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * This file is part of the Contiki desktop environment
31 *
oliverschmidtcd89bec2005-04-10 19:23:47 +000032 * $Id: wget.c,v 1.3 2005/04/10 19:23:47 oliverschmidt Exp $
adamdunkels14fb5fc2003-08-20 22:36:44 +000033 *
34 */
35
36
37#include "ctk.h"
38#include "dispatcher.h"
39#include "webclient.h"
40#include "resolv.h"
41#include "petsciiconv.h"
42#include "uip_main.h"
43#include "loader.h"
44
45#include <stdio.h>
46#include <string.h>
47#include <fcntl.h>
48
49
50static struct ctk_window window;
51
52static struct ctk_label urllabel =
53 {CTK_LABEL(0, 1, 4, 1, "URL:")};
54static char url[80];
55static char urledit[80];
56struct ctk_textentry urltextentry =
57 {CTK_TEXTENTRY(5, 1, 29, 1, urledit, 78)};
58
59/*static struct ctk_label hostlabel =
60 {CTK_LABEL(0, 1, 7, 1, "Server:")};
61static char hostedit[40];
62static char host[40];
63static struct ctk_textentry hosttextentry =
64 {CTK_TEXTENTRY(8, 1, 26, 1, hostedit, 38)};
65
66static struct ctk_label filelabel =
67 {CTK_LABEL(0, 3, 5, 1, "File:")};
68static char fileedit[40];
69static char file[40];
70static struct ctk_textentry filetextentry =
71{CTK_TEXTENTRY(8, 3, 26, 1, fileedit, 38)};*/
72
73
74static struct ctk_label savefilenamelabel =
75 {CTK_LABEL(0, 3, 14, 1, "Save filename:")};
76static char savefilename[40];
77static struct ctk_textentry savefilenametextentry =
78 {CTK_TEXTENTRY(15, 3, 19, 1, savefilename, 38)};
79
80static struct ctk_button filebutton =
81 {CTK_BUTTON(0, 5, 13, "Download file")};
82
83static struct ctk_button d64button =
84 {CTK_BUTTON(17, 5, 18, "Download D64 disk")};
85
86static struct ctk_label statustext =
87 {CTK_LABEL(0, 7, 36, 1, "")};
88static char statusmsg[40];
89
90static struct ctk_window d64dialog;
91static struct ctk_label overwritelabel =
92 {CTK_LABEL(0, 1, 36, 1, "This will overwrite the entire disk!")};
93static struct ctk_label makesurelabel1 =
94 {CTK_LABEL(7, 3, 22, 1, "Make sure you have the")};
95static struct ctk_label makesurelabel2 =
96 {CTK_LABEL(6, 4, 24, 1, "right disk in the drive!")};
97static struct ctk_button overwritebutton =
98 {CTK_BUTTON(2, 6, 14, "Overwrite disk")};
99static struct ctk_button cancelbutton =
100 {CTK_BUTTON(26, 6, 6, "Cancel")};
101
102static DISPATCHER_SIGHANDLER(wget_sighandler, s, data);
103static struct dispatcher_proc p =
104 {DISPATCHER_PROC("Web downloader", NULL, wget_sighandler, webclient_appcall)};
105static ek_id_t id;
106
107/* State */
108
109#define DLOAD_NONE 0
110#define DLOAD_FILE 1
111#define DLOAD_D64 2
112static u8_t dload_state;
113static unsigned long dload_bytes;
114
115int d64file;
116
117struct drv_state {
118 u8_t track;
119 u8_t sect;
120};
121
122static struct drv_state ds;
123
124static char buffer[256];
125static u16_t bufferptr;
126
127/*-----------------------------------------------------------------------------------*/
128/* wget_init();
129 *
130 * Initializes and starts the web browser. Called either at startup or
131 * to open the browser window.
132 */
133LOADER_INIT_FUNC(wget_init)
134{
135 if(id == EK_ID_NONE) {
136 id = dispatcher_start(&p);
137
138 /* Create the main window. */
139 ctk_window_new(&window, 36, 8, "Web downloader");
140
141 /* CTK_WIDGET_ADD(&window, &hostlabel);
142 CTK_WIDGET_ADD(&window, &hosttextentry);
143
144 CTK_WIDGET_ADD(&window, &filelabel);
145 CTK_WIDGET_ADD(&window, &filetextentry);*/
146
147 CTK_WIDGET_ADD(&window, &urllabel);
148 CTK_WIDGET_ADD(&window, &urltextentry);
149
150 CTK_WIDGET_ADD(&window, &savefilenamelabel);
151 CTK_WIDGET_ADD(&window, &savefilenametextentry);
152
153 CTK_WIDGET_ADD(&window, &filebutton);
154
155 CTK_WIDGET_ADD(&window, &d64button);
156
157 CTK_WIDGET_ADD(&window, &statustext);
158
159 /* memset(hostedit, 0, sizeof(hostedit));
160 memset(fileedit, 0, sizeof(fileedit));*/
161 dload_state = DLOAD_NONE;
162
163 memset(savefilename, 0, sizeof(savefilename));
164 memset(url, 0, sizeof(url));
165
166 ctk_dialog_new(&d64dialog, 36, 8);
167 CTK_WIDGET_ADD(&d64dialog, &overwritelabel);
168 CTK_WIDGET_ADD(&d64dialog, &makesurelabel1);
169 CTK_WIDGET_ADD(&d64dialog, &makesurelabel2);
170 CTK_WIDGET_ADD(&d64dialog, &overwritebutton);
171 CTK_WIDGET_ADD(&d64dialog, &cancelbutton);
172
173
174 /* Attach as a listener to a number of signals ("Button activate",
175 "Hyperlink activate" and "Hyperlink hover", and the resolver's
176 signal. */
177 dispatcher_listen(ctk_signal_window_close);
178 dispatcher_listen(ctk_signal_button_activate);
179 dispatcher_listen(ctk_signal_hyperlink_activate);
180 dispatcher_listen(resolv_signal_found);
181 }
182 ctk_window_open(&window);
183}
184/*-----------------------------------------------------------------------------------*/
185static void
186show_statustext(char *text)
187{
188 ctk_label_set_text(&statustext, text);
189 CTK_WIDGET_REDRAW(&statustext);
190}
191/*-----------------------------------------------------------------------------------*/
192/* open_url():
193 *
194 * Called when the URL present in the global "url" variable should be
195 * opened. It will call the hostname resolver as well as the HTTP
196 * client requester.
197 */
198static void
199start_get(void)
200{
201 u16_t addr[2];
202 unsigned char i;
203 static char host[32];
204 char *file;
205 register char *urlptr;
206 unsigned short port;
207
208 /* Trim off any spaces in the end of the url. */
209 urlptr = url + strlen(url) - 1;
210 while(*urlptr == ' ' && urlptr > url) {
211 *urlptr = 0;
212 --urlptr;
213 }
214
215 /* Don't even try to go further if the URL is empty. */
216 if(urlptr == url) {
217 return;
218 }
219
220 /* See if the URL starts with http://, otherwise prepend it. */
221 if(strncmp(url, http_http, 7) != 0) {
222 while(urlptr >= url) {
223 *(urlptr + 7) = *urlptr;
224 --urlptr;
225 }
226 strncpy(url, http_http, 7);
227 }
228
229 /* Find host part of the URL. */
230 urlptr = &url[7];
231 for(i = 0; i < sizeof(host); ++i) {
232 if(*urlptr == 0 ||
233 *urlptr == '/' ||
234 *urlptr == ' ' ||
235 *urlptr == ':') {
236 host[i] = 0;
237 break;
238 }
239 host[i] = *urlptr;
240 ++urlptr;
241 }
242
243 /* XXX: Here we should find the port part of the URL, but this isn't
244 currently done because of laziness from the programmer's side
245 :-) */
246
247 /* Find file part of the URL. */
248 while(*urlptr != '/' && *urlptr != 0) {
249 ++urlptr;
250 }
251 if(*urlptr == '/') {
252 file = urlptr;
253 } else {
254 file = "/";
255 }
256
257
258 /* First check if the host is an IP address. */
259 if(uip_main_ipaddrconv(host, (unsigned char *)addr) == 0) {
260
261 /* Try to lookup the hostname. If it fails, we initiate a hostname
262 lookup and print out an informative message on the
263 statusbar. */
264 if(resolv_lookup(host) == NULL) {
265 resolv_query(host);
266 show_statustext("Resolving host...");
267 return;
268 }
269 }
270
271 /* The hostname we present in the hostname table, so we send out the
272 initial GET request. */
273 if(webclient_get(host, 80, file) == 0) {
274 show_statustext("Out of memory error.");
275 } else {
276 show_statustext("Connecting...");
277 }
278}
279/*-----------------------------------------------------------------------------------*/
280static
281DISPATCHER_SIGHANDLER(wget_sighandler, s, data)
282{
283 int ret;
284 static unsigned char i;
285 DISPATCHER_SIGHANDLER_ARGS(s, data);
286
287 if(s == ctk_signal_button_activate) {
288 if(data == (void *)&filebutton) {
289 /* ret = cbm_open(2, 8, 2, savefilename);*/
290 if(ret == -1) {
291 sprintf(statusmsg, "Open error with '%s'", savefilename);
292 show_statustext(statusmsg);
293 } else {
294 /* strncpy(host, hostedit, sizeof(host));
295 strncpy(file, fileedit, sizeof(file));*/
296 /* petsciiconv_toascii(host, sizeof(host));
297 petsciiconv_toascii(file, sizeof(file));*/
298 strncpy(url, urledit, sizeof(url));
299 petsciiconv_toascii(url, sizeof(url));
300 start_get();
301 dload_bytes = 0;
302 dload_state = DLOAD_FILE;
303 }
304 } else if(data == (void *)&d64button) {
305 ctk_dialog_open(&d64dialog);
306 } else if(data == (void *)&cancelbutton) {
307 ctk_dialog_close();
308 } else if(data == (void *)&overwritebutton) {
309 ctk_dialog_close();
310 /* strncpy(host, hostedit, sizeof(host));
311 strncpy(file, fileedit, sizeof(file));
312 petsciiconv_toascii(host, sizeof(host));
313 petsciiconv_toascii(file, sizeof(file));*/
314 strncpy(url, urledit, sizeof(url));
315 petsciiconv_toascii(url, sizeof(url));
316 start_get();
317 dload_bytes = 0;
318 dload_state = DLOAD_D64;
oliverschmidtcd89bec2005-04-10 19:23:47 +0000319 d64file = open("d64.d64", O_CREAT|O_TRUNC|O_WRONLY);
adamdunkels14fb5fc2003-08-20 22:36:44 +0000320 ds.track = 1;
321 ds.sect = 0;
322 bufferptr = 0;
323 }
324 } else if(s == ctk_signal_hyperlink_activate) {
325 if(dload_state == DLOAD_NONE) {
326 /* open_link(w->widget.hyperlink.url);*/
327 strncpy(urledit,
328 ((struct ctk_widget *)data)->widget.hyperlink.url, sizeof(urledit));
329 petsciiconv_topetscii(urledit, sizeof(urledit));
330 CTK_WIDGET_REDRAW(&urltextentry);
331 CTK_WIDGET_FOCUS(&window, &urltextentry);
332 }
333 } else if(s == resolv_signal_found) {
334 /* Either found a hostname, or not. */
335 if((char *)data != NULL &&
336 resolv_lookup((char *)data) != NULL) {
337 start_get();
338 } else {
339 show_statustext("Host not found.");
340 }
341 } else if(s == ctk_signal_window_close) {
342 dispatcher_exit(&p);
343 id = EK_ID_NONE;
344 LOADER_UNLOAD();
345 }
346}
347/*-----------------------------------------------------------------------------------*/
348/* webclient_aborted():
349 *
350 * Callback function. Called from the webclient when the HTTP
351 * connection was abruptly aborted.
352 */
353void
354webclient_aborted(void)
355{
356 show_statustext("Connection reset by peer");
357}
358/*-----------------------------------------------------------------------------------*/
359/* webclient_timedout():
360 *
361 * Callback function. Called from the webclient when the HTTP
362 * connection timed out.
363 */
364void
365webclient_timedout(void)
366{
367 show_statustext("Connection timed out");
368 if(dload_state == DLOAD_FILE) {
369 /* cbm_close(2);*/
370 }
371
372}
373/*-----------------------------------------------------------------------------------*/
374/* webclient_closed():
375 *
376 * Callback function. Called from the webclient when the HTTP
377 * connection was closed after a request from the "webclient_close()"
378 * function. .
379 */
380void
381webclient_closed(void)
382{
383 show_statustext("Done.");
384}
385/*-----------------------------------------------------------------------------------*/
386/* webclient_closed():
387 *
388 * Callback function. Called from the webclient when the HTTP
389 * connection is connected.
390 */
391void
392webclient_connected(void)
393{
394 show_statustext("Request sent...");
395}
396/*-----------------------------------------------------------------------------------*/
397/*-----------------------------------------------------------------------------------*/
398static void
399write_buffer(void)
400{
401 char buf2[256];
402 int i;
403
404 for(i = 0; i < 256; ++i) {
405 buf2[i] = i;
406 }
407
408 write(d64file, buf2, 256);
409 write(d64file, buffer, 256);
410 /* write_sector(8, ds.track, ds.sect, buffer);
411 if(next_sector() != 0) {
412 dload_state = DLOAD_NONE;
413 }*/
414}
415static void
416handle_d64_data(char *data, u16_t len)
417{
418 u16_t bufferlen;
419
420 while(dload_state == DLOAD_D64 &&
421 len > 0) {
422 bufferlen = sizeof(buffer) - bufferptr;
423 if(len < bufferlen) {
424 bufferlen = len;
425 }
426
427 memcpy(&buffer[bufferptr], data, bufferlen);
428
429 data += bufferlen;
430 bufferptr += bufferlen;
431 len -= bufferlen;
432
433 if(bufferptr == sizeof(buffer)) {
434 write_buffer();
435 bufferptr = 0;
436 }
437 }
438}
439/*-----------------------------------------------------------------------------------*/
440/* webclient_datahandler():
441 *
442 * Callback function. Called from the webclient module when HTTP data
443 * has arrived.
444 */
445void
446webclient_datahandler(char *data, u16_t len)
447{
448 int ret;
449
450 if(len > 0) {
451 dload_bytes += len;
452 sprintf(statusmsg, "Downloading (%lu bytes)", dload_bytes);
453 show_statustext(statusmsg);
454 if(dload_state == DLOAD_D64) {
455 handle_d64_data(data, len);
456 } else if(dload_state == DLOAD_FILE) {
457 /* ret = cbm_write(2, data, len); */
458 if(ret != len) {
459 sprintf(statusmsg, "Wrote only %d bytes", ret);
460 show_statustext(statusmsg);
461 }
462 }
463 }
464
465 if(data == NULL) {
466 if(dload_state == DLOAD_FILE) {
467 /* cbm_close(2);*/
468 }
469 close(d64file);
470 dload_state = DLOAD_NONE;
471 sprintf(statusmsg, "Finished downloading %lu bytes", dload_bytes);
472 show_statustext(statusmsg);
473 }
474}
475/*-----------------------------------------------------------------------------------*/