source: golgotha/src/test/web_crawl/win.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 14 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 10.1 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "network/net_prot.hh"
10
11#include "win.hh"
12#include "threads/threads.hh"
13#include "fb_thread.hh"
14#include "font/font.hh"
15#include "gui/button.hh"
16#include "gui/text.hh"
17#include "url.hh"
18#include "network/net_sock.hh"
19#include "lisp/lisp.hh"
20#include <ctype.h>
21
22
23char *fb_thread_window::get_error_string()
24{
25  switch (last_error)
26  {
27    case FB_NO_ERROR : return "ok"; break;
28    case FB_TIMED_OUT : return "timeout"; break;
29    case FB_URL_TOO_BIG : return "url too big"; break;
30    case FB_END_OF_STREAM : return "end of stream"; break;
31    case FB_NOT_IN_INCLUDE_LIST : return "not in include list"; break;
32    case FB_NO_EXTENSION : return "no file extension"; break;
33    case FB_NO_FILENAME : return "no filename"; break;
34    case FB_FILE_EXSIST : return "file exsist"; break;
35    case FB_NO_WRITE_OPEN : return "couldn't open write file"; break;
36    case FB_IN_EXCLUDE_LIST : return "in exclusion list"; break;
37    case FB_NO_CONNECT : return "connect failed"; break;
38    case FB_USER_ABORTED : return "user aborted"; break;
39    default : return "unknown error"; break;
40  }
41  last_error=FB_NO_ERROR;
42}
43   
44
45
46void fb_thread_window::stop_thread()
47{
48  if (state!=FB_WAITING && state!=FB_DONE_READING)
49    stopping=1;
50     
51  while (state!=FB_WAITING && state!=FB_DONE_READING)
52    i4_thread_yield();
53}
54
55void fb_thread_window::add_button(char *name, cmd_type cmd)
56{
57  i4_text_window_class *tw=new i4_text_window_class(name, style,
58                                                    style->font_hint->small_font);
59
60  i4_button_class *b;
61  b=new i4_button_class(0, tw, style, new i4_event_reaction_class(this, cmd));
62  b->set_popup(i4_T);
63  button_x-=(int)b->width();
64  add_child(button_x, 0, b); 
65}
66
67
68
69
70void fb_thread_window::read_data()
71{
72  w8 packet[1024];               
73  int s=sock->read(packet,1024);
74  last_read.get();
75     
76  if (s>0)    // read 0 or less, assume end of stream
77  {   
78    if (save_file)
79    {
80      save_file->write(packet, s);
81      save_buffer_size+=s;
82    }
83    else
84    {   
85      // we are going to overflow our buffer
86      if (save_buffer_size+s > FB_MAX_SAVE_BUFFER_SIZE)
87      {
88        last_error=FB_URL_TOO_BIG;
89        state=FB_DONE_READING;  // tell main program to process what we read of url
90      }
91      else
92      {
93        memcpy(save_buffer + save_buffer_size, packet, s);
94        save_buffer_size+=s;
95      }
96    }   
97  }
98  else
99  {
100    last_error=FB_END_OF_STREAM;
101
102    if (save_file)
103    {
104      close_save_file(i4_F);
105      state=FB_WAITING;         // ready for another request
106      save_buffer_size=0;
107    }
108    else
109    {
110      state=FB_DONE_READING;    // tell main program to process this url
111     
112    }
113   
114    if (sock)
115    {
116      delete sock;
117      sock=0;
118    }
119  }
120}
121
122char *nocase_strstr(char *hay, char *needle)
123{
124  while (*hay)
125  {
126    char *a1, *a2;
127    int not_equal=0;
128   
129    for (a1=hay, a2=needle; *a1 && *a2; )
130    {
131      if (toupper(*a1)!=toupper(*a2))
132        not_equal=1;
133      a1++;
134      a2++;
135    }
136
137    if (*a2) not_equal=1;
138
139    if (!not_equal)
140      return hay;
141   
142    hay++;
143  }
144  return 0;
145}
146
147void fb_thread_window::set_url(fb_url *new_url)
148{
149  stop_thread();
150  save_buffer_size=0;
151 
152
153  close_save_file();
154   
155  if (sock)
156  {
157    delete sock;
158    sock=0;
159  }
160   
161    if (url)
162      delete url;
163 
164  url=new_url;
165 
166  li_object *o;
167 
168  for (o=li_get_value("exclude_sub_strings",0); o; o=li_cdr(o,0))
169    if (nocase_strstr(url->full_name, li_string::get(li_car(o,0),0)->value()))
170    {
171      last_error=FB_IN_EXCLUDE_LIST;
172      state=FB_DONE_READING;
173      return ;
174    }
175
176  int save=0;
177  char *ext=url->get_extension();     
178  if (ext)
179  {
180 
181    o=li_get_value("include_sub_strings");
182    if (o)
183    {
184      int ok=0;
185   
186      while (o && !ok)
187      {
188        li_object *i=li_car(o,0);
189        if (fb_strneq( li_get_string(li_car(i,0),0), ext, strlen(ext)))
190        {
191          i=li_cdr(i,0);
192          if (!i)
193            ok=1;
194          else
195          {
196            for (i=li_cdr(i,0); i; i=li_cdr(i,0))
197              if (nocase_strstr(url->full_name, li_string::get(li_car(i,0),0)->value()))
198                ok=1;
199
200            if (!ok)
201              i4_debug->printf("not listed '%s'\n", url->full_name);
202
203          }
204        }
205        o=li_cdr(o,0);
206      }
207
208      int l=strlen(url->full_name)-1;
209      if (!ok && url->full_name[l]!='/' && url->full_name[l]!='\\')
210      {
211        last_error=FB_NOT_IN_INCLUDE_LIST;
212        state=FB_DONE_READING;
213        return ;
214      }
215    }
216
217    for (o=li_get_value("save_extensions",0); o; o=li_cdr(o,0))
218      if (strcmp(li_string::get(li_car(o,0),0)->value(), ext)==0)
219        save=1;
220
221  }
222   
223
224
225  if (save)
226  {
227    char *fn=url->get_filename();     
228    if (!fn)
229    {
230      last_error=FB_NO_FILENAME;
231      state=FB_DONE_READING;
232      return ;
233    }
234
235    char filename[200];
236    sprintf(filename, "%s%s", li_string::get(li_get_value("save_path",0),0)->value(), fn);
237
238    i4_file_status_struct stat;
239   
240    if (i4_get_status(filename, stat))
241    {
242      last_error=FB_FILE_EXSIST;
243      state=FB_DONE_READING;
244      return ;
245    }
246     
247    save_file=i4_open(filename, I4_WRITE);
248    if (!save_file)
249    {
250      last_error=FB_NO_WRITE_OPEN;
251      state=FB_DONE_READING;
252      return ;
253    }
254  }
255
256  state=FB_CONNECTING;        // let the thread do the nameserver lookup
257}
258
259
260void fb_thread_window::receive_event(i4_event *ev)
261{
262  if (ev->type()==i4_event::USER_MESSAGE)
263  {
264    switch (((i4_user_message_event_class *)ev)->sub_type)
265    {
266      case PAUSE :
267        if (state==FB_READING) 
268          state=FB_SUSPENDED_READ;
269        else if (state==FB_SUSPENDED_READ)
270          state=FB_READING;
271        break;
272       
273      case ABORT :
274        stopping=1;
275        break;
276       
277      case BAN_DIR :
278      case BAN_SITE :
279        break;
280    }
281  }
282 
283  i4_parent_window_class::receive_event(ev);
284}
285
286fb_thread_window::fb_thread_window(w16 w, w16 h, i4_graphical_style_class *style)
287  : i4_parent_window_class(w,h), style(style)
288{
289  stopping=0;
290  prot=i4_get_typed_protocol(I4_TCPIP);
291  if (!prot) i4_error("no TCPIP in program");
292 
293  save_buffer_size=0;
294  sock=0;
295  save_file=0;
296  url=0;
297
298  last_error=FB_NO_ERROR;
299  state=FB_THREAD_INIT;
300  i4_add_thread(fb_thread, 100*1024, this);
301 
302  button_x=width();
303 
304  add_button("Pause", PAUSE);
305  add_button("Abort", ABORT);
306  add_button("Ban Dir", BAN_DIR);
307  add_button("Ban Site", BAN_SITE); 
308}
309
310// called from main program to see if window needs to be redrawn
311void fb_thread_window::update()  // check to see if we need to update the window
312{
313  i4_time_class now;
314 
315  if (now.milli_diff(last_refresh)>200)    // refresh every .2 secs
316  {
317    if (last_state!=state ||
318        last_save_buffer_size!=save_buffer_size)     
319      request_redraw(i4_F);
320  }
321}
322
323
324// called by main program when window some time after window calls request_redraw
325void fb_thread_window::parent_draw(i4_draw_context_class &context)
326{
327  style->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);
328
329  i4_font_class *font=style->font_hint->small_font;
330  i4_font_class *bfont=style->font_hint->normal_font;
331 
332  char *state_names[]={"Thread Init",
333                       "Idle",
334                       "Connecting",
335                       "Reading",
336                       "Paused",
337                       "Done Reading",
338                       "Stopping",
339                       "Quiting",
340                       "Done"};
341
342  bfont->set_color(0xffff00);
343
344  int x=0, y=0;
345  bfont->put_string(local_image, x,y, state_names[state], context);
346  y+=bfont->height(state_names[state])+4;
347
348  if (url && state==FB_CONNECTING || state==FB_READING ||
349      state==FB_DONE_READING || state==FB_SUSPENDED_READ)
350  {
351    font->set_color(0x7f);
352    font->put_string(local_image, x,y, url->full_name, context);
353  }
354  y+=font->largest_height();
355
356
357  if (state==FB_READING || state==FB_DONE_READING || state==FB_SUSPENDED_READ)
358  {
359    char buf[100];
360    font->set_color(0x7f0000);
361    sprintf(buf, "%d bytes read", save_buffer_size);
362    font->put_string(local_image, x,y, buf, context);
363  }
364
365  last_state=state;
366  last_save_buffer_size=save_buffer_size;
367 
368  last_refresh.get();
369 
370}
371
372// waits for thread to stop before closing the window
373fb_thread_window::~fb_thread_window()
374{
375  state=FB_THREAD_QUITING;
376  while (state!=FB_THREAD_DONE)
377    i4_thread_yield();
378}
379
380
381void fb_thread_window::check_for_timeout()
382{
383  i4_time_class now;
384  int secs=now.milli_diff(last_read)/1000;  // time in secs
385 
386  if (secs!=last_sec)
387  {
388    last_sec=secs;
389       
390    for (li_object *o=li_get_value("timeouts",0); o; o=li_cdr(o,0))
391    {
392      int size=li_int::get(li_first(li_car(o,0),0),0)->value();
393      int tout=li_int::get(li_second(li_car(o,0),0),0)->value();
394
395     
396      if (save_buffer_size<size && secs>tout)
397      {
398        last_error=FB_TIMED_OUT;
399        state=FB_DONE_READING;
400        return ;
401      }
402    }
403  }
404}
405
406 // closes save file if need, and deletes it if it's too small
407void fb_thread_window::close_save_file(int wait_on_thread)
408{
409  if (save_file)
410  {
411    if (wait_on_thread)
412      stop_thread();
413   
414    int need_del = save_file->tell() < li_int::get(li_get_value("save_min_size",0),0)->value() ? 1 : 0;
415     
416    delete save_file;
417    save_file=0;
418
419    if (url && need_del)
420    {
421      char filename[200];
422      sprintf(filename, "%s%s", li_string::get(li_get_value("save_path",0),0)->value(),
423              url->get_filename());
424      i4_unlink(filename);
425    }
426  }
427}
Note: See TracBrowser for help on using the repository browser.