root/gsdl/trunk/runtime-src/src/w32server/fnord.cpp @ 20949

Revision 20949, 38.0 KB (checked in by ak19, 10 years ago)

Need to write out hostIP in case we were using this address-resolution-method, and then next time started up the apache server instead of server.exe.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1/**********************************************************************
2 *
3 * fnord.cpp
4 * Copyright (C) 1996
5 *
6 * A component of the fnord webserver written by bmorin@wpi.edu.
7 *
8 * Altered for use with the Greenstone digital library software by the
9 * New Zealand Digital Library Project at the University of Waikato,
10 * New Zealand.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 *********************************************************************/
27
28#include "text_t.h"
29#include <windows.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <memory.h>
34#pragma hdrstop
35#include "netio.h"
36#include "settings.h"
37#include "httpsrv.h"
38#include "resource.h"
39#include "locate.h"
40#include "cgiwrapper.h"
41#include "startbrowser.h"
42#include "d_winsock.h"
43#include "fileutil.h"
44
45#define MAINWINDOWWIDTH 400
46#define MAINWINDOWHEIGHT 200
47
48#define WASTEHEIGHT 44  // Error in ht due to caption and menu bar
49#define WASTEWIDTH 6
50#define SPACERWIDTH 5
51
52// size and position of the collection title
53#define COLTITLEWIDTH 351
54#define COLTITLEHEIGHT 35
55#define COLTITLEX ((MAINWINDOWWIDTH-COLTITLEWIDTH)/2)
56#define COLTITLEY 10
57
58// size and position of the version string
59#define VERSIONWIDTH MAINWINDOWWIDTH
60#define VERSIONHEIGHT 20
61#define VERSIONX 0
62#define VERSIONY (COLTITLEY+COLTITLEHEIGHT)
63
64// size and position of the Greenstone digital library logo
65#define LOGOWIDTH 135
66#define LOGOHEIGHT 55
67#define LOGOX (MAINWINDOWWIDTH-(LOGOWIDTH+SPACERWIDTH))
68#define LOGOY (MAINWINDOWHEIGHT-(LOGOHEIGHT+SPACERWIDTH))
69
70// size and position of the enter button
71#define ENTERBUTTONWIDTH 160
72#define ENTERBUTTONHEIGHT 30
73#define ENTERBUTTONX SPACERWIDTH
74#define ENTERBUTTONY ((MAINWINDOWHEIGHT-(LOGOHEIGHT+SPACERWIDTH))-(ENTERBUTTONHEIGHT+SPACERWIDTH))
75
76// size and position of the enter string
77#define ENTERSTRINGX (ENTERBUTTONX+ENTERBUTTONWIDTH+SPACERWIDTH)
78#define ENTERSTRINGY ENTERBUTTONY
79#define ENTERSTRINGWIDTH (MAINWINDOWWIDTH-(ENTERBUTTONWIDTH+SPACERWIDTH+SPACERWIDTH+SPACERWIDTH))
80#define ENTERSTRINGHEIGHT ENTERBUTTONHEIGHT
81
82// size and position of the info string
83#define INFOWIDTH MAINWINDOWWIDTH
84#define INFOHEIGHT (MAINWINDOWHEIGHT-INFOY)
85#define INFOX 0
86#define INFOY ENTERBUTTONY
87
88// size and position of restricted buttons
89#define ALTERNATIVEBUTTONWIDTH 160
90#define ALTERNATIVEBUTTONHEIGHT 30
91#define ALTERNATIVEBUTTONX SPACERWIDTH
92#define ALTERNATIVEBUTTONY LOGOY
93
94#define INFOBUTTONWIDTH 30
95
96// size and position of restart button
97#define RESTARTBUTTONWIDTH 160
98#define RESTARTBUTTONHEIGHT 30
99#define RESTARTBUTTONX 50
100#define RESTARTBUTTONY (MAINWINDOWHEIGHT-RESTARTBUTTONHEIGHT-15)
101
102const char versionstring[] = "version " GSDL_VERSION;
103
104const char strnothing[] = "";
105const char strinit[] = "Initialising...";
106const char strsb[] = "Starting browser...";
107const char strrestartlib[] = "Press the 'Restart Library' button to start a browser\n"
108"and enter library";
109const char strenterlib[] = "Press this button to begin using\n"
110"the library";
111const char *enterstring = NULL; // points to the current enter string
112const char *infostring = NULL; // points to the current info string
113
114
115// globals to do with networking and browsers
116int have_networking = 0;
117int netscapeneeded = 0;
118char startbrowserdir[1024] = ""; // HARD LIMIT!!!!!
119
120
121// stats to do with the last time the enter library button was pressed
122// these stats are needed to make suggestions about the proxy
123int enterlib_libaccessnum = -1; // -1 = NA
124DWORD enterlib_time = 0;
125
126
127enum { undefined_window, console_window, plain_window }
128window_state;
129
130HDC coltitledc = NULL;
131HBITMAP defcoltitlebitmap = NULL, coltitlebitmap=NULL;
132
133HDC logodc=NULL;
134HBITMAP deflogobitmap=NULL, logobitmap=NULL;
135
136HWND GoButton = NULL;
137HWND Enter = NULL;
138// HWND EnterRestricted = NULL;
139// HWND InfoRestricted = NULL;
140int init_type = 0;
141int init_done = 0;
142
143
144// Added an argument so you can specify not to do any of the windows orientated clean up - jmt12 18/11/2003
145void finish_up(bool init_only) {
146  // remember the current preferences
147  write_settings("");
148
149  if(init_only) {
150    return;
151  }
152   
153 // Shutdown the HTTP server
154  EndHTTPServer();
155 
156  // Shutdown the main server modules
157  CleanUpNetIO();
158  //    RemoveFnordFromTray();
159 
160  // Unload the wsock32 dll
161  d_UnloadWinsock();
162 
163  // Clean up graphics stuff from window
164 
165  if (defcoltitlebitmap != NULL)
166    SelectObject (coltitledc, defcoltitlebitmap);
167  if (coltitlebitmap != NULL)
168    DeleteObject (coltitlebitmap);
169  if (coltitledc != NULL)
170    DeleteDC (coltitledc);
171 
172  if (deflogobitmap != NULL)
173    SelectObject (logodc, deflogobitmap);
174  if (logobitmap != NULL)
175    DeleteObject (logobitmap);
176  if (logodc != NULL)
177    DeleteDC (logodc);
178 
179  // Shutdown the main window
180  PostQuitMessage(0);
181}
182
183
184int overlap(int left, int top, int right, int bottom,
185            RECT &r2)
186{
187  if (left <= r2.right && r2.left <= right &&
188      top <= r2.bottom && r2.top <= bottom)
189    return 1;
190  else
191    return 0;
192}
193
194
195void paint_window (HDC pdc, RECT &updateRect) {
196  // make sure the various DCs are set up
197  if (coltitledc == NULL) {
198    coltitledc = CreateCompatibleDC(pdc);
199    defcoltitlebitmap = (HBITMAP)SelectObject (coltitledc, coltitlebitmap);
200  }
201 
202  if (logodc == NULL) {
203    logodc = CreateCompatibleDC(pdc);
204    deflogobitmap = (HBITMAP)SelectObject (logodc, logobitmap);
205  }
206
207  // remove any remaining sign of initial buttons
208  if (init_done && (overlap (ENTERBUTTONX, ENTERBUTTONY, ENTERBUTTONX+ENTERBUTTONWIDTH,
209        ALTERNATIVEBUTTONY+ALTERNATIVEBUTTONHEIGHT, updateRect))) {
210    RECT initRect;
211    initRect.left = ENTERBUTTONX;
212    initRect.top = ENTERBUTTONY;
213    initRect.right = ENTERBUTTONX+ENTERBUTTONWIDTH;
214    initRect.bottom = ALTERNATIVEBUTTONY+ALTERNATIVEBUTTONHEIGHT;
215    FillRect(pdc, &initRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
216  }
217
218  // update the collection title if needed
219  if (overlap(COLTITLEX, COLTITLEY,
220          COLTITLEX+COLTITLEWIDTH, COLTITLEY+COLTITLEHEIGHT,
221          updateRect)) {
222    BitBlt (pdc, COLTITLEX, COLTITLEY,
223        COLTITLEX+COLTITLEWIDTH, COLTITLEY+COLTITLEHEIGHT,
224        coltitledc, 0, 0, SRCCOPY);
225  }
226 
227  // update the version string if needed
228  if (overlap (VERSIONX, VERSIONY,
229           VERSIONX+VERSIONWIDTH, VERSIONY+VERSIONHEIGHT,
230           updateRect)) {
231    RECT versionRect;
232    versionRect.left = VERSIONX;
233    versionRect.top = VERSIONY;
234    versionRect.right = VERSIONX+VERSIONWIDTH;
235    versionRect.bottom = VERSIONY+VERSIONHEIGHT;
236    DrawText(pdc, versionstring, -1, &versionRect, DT_CENTER);
237  }
238 
239  // decide what we want to draw
240  if (init_done && gsdl_show_console) {
241    // we want to draw a "console" window
242    if (window_state != console_window ||
243    overlap (text_rect.left, text_rect.top,
244         text_rect.right, text_rect.bottom,
245         updateRect)) {
246      refresh_console (pdc);
247    }
248   
249    window_state = console_window;
250   
251  } else {
252    // we want to draw a "plain" window
253   
254    // update the enter string if needed
255    if (overlap (ENTERSTRINGX, ENTERSTRINGY, ENTERSTRINGX+ENTERSTRINGWIDTH,
256         ENTERSTRINGY+ENTERSTRINGHEIGHT, updateRect)) {
257
258    RECT enterstringRect;
259    enterstringRect.left = ENTERSTRINGX;
260    enterstringRect.top = ENTERSTRINGY;
261    enterstringRect.right = ENTERSTRINGX+ENTERSTRINGWIDTH;
262    enterstringRect.bottom = ENTERSTRINGY+ENTERSTRINGHEIGHT;
263    FillRect(pdc, &enterstringRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
264
265    if ((enterstring != NULL) && (strlen(enterstring) > 0)) {
266     
267      int cury = ENTERSTRINGY;
268      int startline = 0, here = 0;
269      while (enterstring[here] != '\0') {
270        if (enterstring[here] < ' ') {
271          if (here - startline > 0) {
272        // output the text
273        TextOut (pdc, ENTERSTRINGX, cury,
274             &enterstring[startline], here-startline);
275        cury += line_spacing;
276          }
277          startline = here+1;
278        }
279        ++here;
280      }
281      // output any remaining text
282      if (here - startline > 0) {
283        TextOut (pdc, ENTERSTRINGX, cury, &enterstring[startline], here-startline);
284      }
285    }
286    }
287   
288    window_state = plain_window;
289  }
290 
291  // update the info string if needed
292  if (init_done && !gsdl_show_console &&
293      ((infostring != NULL) && overlap (INFOX, INFOY,
294                    INFOX+INFOWIDTH, INFOY+INFOHEIGHT,
295                    updateRect))) {
296    RECT infoRect;
297    infoRect.left = INFOX;
298    infoRect.top = INFOY;
299    infoRect.right = INFOX+INFOWIDTH;
300    infoRect.bottom = INFOY+INFOHEIGHT;
301    FillRect(pdc, &infoRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
302    DrawText(pdc, infostring, -1, &infoRect, DT_CENTER);
303  }
304
305  // update the logo (always)
306  BitBlt (pdc, LOGOX, LOGOY, LOGOX+LOGOWIDTH, LOGOY+LOGOHEIGHT,
307      logodc, 0, 0, SRCCOPY);
308}
309
310
311void handle_painting (HWND Window) {
312  HDC pdc;  PAINTSTRUCT ps;
313  pdc = BeginPaint(Window, &ps);
314 
315  paint_window (pdc, ps.rcPaint);
316 
317  EndPaint(Window, &ps);
318}
319
320
321// returns 1 on success, 0 otherwise
322int enter_library (HWND Window) {
323  int res;
324 
325  if (infostring == strrestartlib) {
326
327    // the "restart library" button was pressed so we want to reinitialize
328    // greenstone, read in all the macrofiles again, etc.
329    gsdl_init(false);
330  }
331
332  // get the url and attempt to start a browser
333  if (have_networking) {
334    // There are now four address resolution methods:
335    //   0: Standard -- get local IP then resolve to a name
336    //   1: IP only -- as above, but use IP only -- don't resolve to a name
337    //   2: localhost -- always use localhost
338    //   3: 127.0.0.1 -- always use 127.0.0.1
339    char gsdl_address[100];
340    char hostIP[25]; // 16 should be enough to represent an IP address + null byte
341
342    DWORD local_ip = GetLocalIP();
343    // always work out the hostIP:
344    sprintf(hostIP, "%d.%d.%d.%d", local_ip & 0xFF, (local_ip >> 8) & 0xFF, (local_ip >> 16) & 0xFF, (local_ip >> 24) & 0xFF);
345
346    if (local_ip == INADDR_ANY || gsdl_address_resolution_method == 3) {
347      local_ip = 127 + (0 << 8) + (0 << 16) + (1 << 24);
348    }
349
350    if (gsdl_address_resolution_method == 1 || gsdl_address_resolution_method == 3) {
351      sprintf(gsdl_address, "%d.%d.%d.%d", local_ip & 0xFF, (local_ip >> 8) & 0xFF, (local_ip >> 16) & 0xFF, (local_ip >> 24) & 0xFF);
352    }
353    else if (gsdl_address_resolution_method == 2) {
354      sprintf(gsdl_address, "localhost");
355    }
356    else {
357      strcpy(gsdl_address, GetLocalName(NULL));
358    }
359
360    text_t url = "http://" + text_t(gsdl_address);
361
362    gsdl_host_IP = text_t(hostIP);
363    gsdl_url = url;
364    write_settings(gsdl_url);
365
366    if (gsdl_port_num != 80) {
367      url += ":" + text_t(gsdl_port_num);
368    }
369    url += gsdl_enterlib;
370
371    // add a unique ending so it will always result in a request
372    text_t::const_iterator it =
373      findchar (gsdl_enterlib.begin(), gsdl_enterlib.end(), '?');
374    if (it == gsdl_enterlib.end()) url.push_back ('?');
375    else url.push_back ('&');
376    int tcount = GetTickCount();
377    url += "uq=" + text_t(tcount);
378   
379    // remember the library access number for later proxy checking
380    enterlib_libaccessnum = libaccessnum;
381   
382    if (gsdl_start_browser) {
383
384      // do a quick check to make sure we're using netscape when
385      // we should be (it might have been just installed)
386      if (netscapeneeded) gsdl_check_browser_settings (netscapeneeded);
387   
388      char *cstr_url = url.getcstr();
389      if (strlen (startbrowserdir) <= 0) {
390    res = startbrowser (cstr_url, gsdl_browser_exe, NULL);
391   
392      } else res = startbrowser (cstr_url, gsdl_browser_exe, startbrowserdir);
393   
394      delete []cstr_url;
395
396    } else {
397      return 1;
398    }
399  }
400 
401  if (res == SB_NOERROR) {
402    // success !!
403   
404    // remember the time the browser was started for later proxy checking
405    if (have_networking) enterlib_time = GetTickCount();
406   
407    return 1;
408  }
409 
410  // no browser was started
411  enterlib_libaccessnum = -1;
412 
413  if ((res == SB_FAIL_BADFORMAT) || (res == SB_FAIL_NOTFOUND)) {
414    if (!netscapeneeded) { // any browser
415      MessageBox(Window,
416         "Failed to start your chosen browser. It seems that your\n"
417         "chosen browser has been removed or corrupted.\n"
418         "Please check your browser choice by going to the\n"
419         "'Settings...' item under the 'File' menu.",
420         "Greenstone Digital Library Software", MB_OK);
421    } else { // netscape used
422      MessageBox(Window,
423         "Failed to start Netscape. It seems that Netscape has\n"
424         "been removed or corrupted. You need Netscape\n"
425         "installed to use the Greenstone Digital Library\n"
426         "software on non-networked machines.",
427         "Greenstone Digital Library Software", MB_OK);
428    }
429   
430  } else {
431    MessageBox(Window,
432           "Failed to start your browser. This may have been\n"
433           "because there was not enough memory available. Shut\n"
434           "down all other applications you have running, and\n"
435           "try again.",
436           "Greenstone Digital Library Software", MB_OK);
437  }
438 
439  return 0; // failed
440}
441
442
443void install_netscape (HWND Window) {
444  char installpath[256];
445 
446  // try to find the browser directory
447  char *gsdlhome = gsdl_gsdlhome.getcstr();
448  strcpy (installpath, gsdlhome); // use gsdlhome to find the CD-ROM drive...
449  delete []gsdlhome;
450 
451  // remove any slashes from the pathname
452  int len = strlen (installpath);
453  while ((len > 0) && ((installpath[len-1] == '\\') || (installpath[len-1] == '/'))) {
454    --len;
455  }
456  // remove '\gsdl'
457  len = len - 5;
458  installpath[len] = '\0';
459 
460  strcat (installpath, "\\netscape\\");
461 
462  // check this directory
463  if (!cstrcheckdir(installpath)) {
464    return;
465  }
466 
467  // get the operating system information
468  OSVERSIONINFO osver;
469  memset(&osver, 0, sizeof(OSVERSIONINFO));
470  osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
471  GetVersionEx(&osver);
472
473  // get the install program for this operating system
474  if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
475    strcat (installpath, "n16e405.exe");
476  } else {
477    strcat (installpath, "n32e405.exe");
478  }
479 
480  // run the install program
481  int res = WinExec (installpath, SW_SHOW);
482  if (res == 0) {
483    // out of resources or memory
484    MessageBox (Window,
485        "Did not have enough resources or memory to run the\n"
486        "install program. Try shutting down all other programs\n"
487        "and trying again.",
488        "Greenstone Digital Library Software",
489        MB_OK|MB_APPLMODAL);
490   
491  } else if (res == ERROR_BAD_FORMAT) {
492    // executable image is corrupt -- ????
493    MessageBox (Window,
494        "The install program seems to be corrupt.",
495        "Greenstone Digital Library Software",
496        MB_OK|MB_APPLMODAL);
497   
498  } else if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_PATH_NOT_FOUND)) {
499    // couldn't find the executable -- ????
500    MessageBox (Window,
501        "Could not find the install program. Try installing\n"
502        "Netscape from the Greenstone Digital Library\n"
503        "software's install program.",
504        "Greenstone Digital Library Software",
505        MB_OK|MB_APPLMODAL);
506  }
507}
508
509void open_help () {
510  char topdir[256], cmd[256];
511 
512  // try to find the browser directory
513  char *gsdlhome = gsdl_gsdlhome.getcstr();
514  strcpy (topdir, gsdlhome); // use gsdlhome to find the CD-ROM drive...
515  delete []gsdlhome;
516  strcpy (cmd, "notepad ");
517 
518  // remove any slashes from the pathname
519  int len = strlen (topdir);
520  while ((len > 0) && ((topdir[len-1] == '\\') || (topdir[len-1] == '/'))) {
521    --len;
522  }
523  // remove the '\gsdl'
524  len = len - 5;
525  topdir[len] = '\0';
526
527  strcat (topdir, "\\README.txt");
528  strcat (cmd, topdir);
529 
530  WinExec (cmd, SW_SHOW);
531}
532
533
534long __stdcall WndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam) {
535  switch(Message) {
536    // Constant Messages
537  case WM_CREATE:
538    break;
539   
540  case WM_COMMAND:
541    if ((GoButton != NULL) && ((HWND)LParam == GoButton)) {
542      // attempt to start a browser
543      gsdl_start_browser = 1;
544      if (enter_library (Window) && !gsdl_show_console)
545        ShowWindow(Window,SW_MINIMIZE);
546
547    } else if ((Enter != NULL) && ((HWND)LParam == Enter)) {
548      init_done = 1;
549      init_type = 1;
550
551//      } else if ((EnterRestricted != NULL) && ((HWND)LParam == EnterRestricted)) {
552//        init_done = 1;
553//        init_type = 0;
554
555//      } else if ((InfoRestricted != NULL) && ((HWND)LParam == InfoRestricted)) {
556//        MessageBox (NULL, "The Greenstone system automatically determines whether your computer has\n"
557//            "network software installed or is connected to a network.  It operates correctly\n"
558//            "under any of these conditions.\n\n"
559//            "The restricted version is intended for use when the standard one\n\n"
560//            "   (a) causes an unwanted telephone dialup operation;\n"
561//            "   (b) fails to run because network software is installed, but installed\n"
562//            "         incorrectly.\n\n"
563//            "The restricted version only works with Netscape (not Internet Explorer).\n\n"
564//            "Unless these problems arise, you should always use the standard version\n"
565//            "(press the 'Enter Library' button).\n",
566//            "Greenstone Digital Library Software",
567//            MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
568
569    } else {
570      switch (LOWORD(WParam)) {
571      case ID_PROJECT_SETTINGS:
572    Settings_Dialog(Window, netscapeneeded);
573    break;
574      case ID_INSTALL_NETSCAPE:
575    install_netscape(Window);
576    break;
577      case IDHELP:
578    open_help();
579    break;
580      case ID_PROJECT_EXIT:
581        finish_up(false);
582        break;
583      default:
584        break;
585      }
586    }
587    break;
588   
589  case WM_PAINT:
590    handle_painting(Window);
591    break;
592   
593  case HTTP_SERVER_MSG:
594    ProcessHTTPServerMsg(WParam, LParam);
595    break;
596   
597  case WM_DESTROY:
598    finish_up(false);
599    break;
600   
601  default:
602    //Unhandled Messages end up here (DefWindowProc)
603    return DefWindowProc(Window, Message, WParam, LParam);
604  }
605 
606  return(0);
607}
608
609// returns 0 if successful,
610// otherwise a WSA error number
611int tryinitnetwork (HANDLE Instance, HWND MsgWindow, char *path) {
612  // try to load winsock
613  int err = d_LoadWinsock (path);
614 
615  if (err == D_NOERROR) {
616    // next, try to init netio
617    err = InitNetIO();
618   
619    if (err == 0) {
620      // next, try to start the http server
621      err = StartHTTPServer(MsgWindow);
622     
623      if (err == 0) {
624    // finally, get the host name (no error value
625    // is returned from this function)
626    GetLocalName((HINSTANCE)Instance);
627   
628      } else {
629    // couldn't start the http server,
630    // deinit netio and unload winsock
631    CleanUpNetIO();
632    d_UnloadWinsock();
633      }
634     
635    } else {
636      // couldn't init netio, unload winsock
637      d_UnloadWinsock();
638    }
639   
640  } else {
641    // couldn't load winsock
642    err = WSASYSNOTREADY;
643  }
644 
645  return err;
646}
647
648
649// inits all the network functionality
650// returns 0 if an unrecoverable error occurred,
651// and 1 if everything successfully initialised.
652int initnetwork (HANDLE Instance, HWND MsgWindow) {
653  OSVERSIONINFO osver;
654 
655  // get the operating system information
656  memset(&osver, 0, sizeof(OSVERSIONINFO));
657  osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
658  GetVersionEx(&osver);
659 
660  // first try to initialise the network with system installed
661  // networking software
662  startbrowserdir[0] = '\0';
663  netscapeneeded = 0;
664  int err = 1;
665  if (init_type == 1) err = tryinitnetwork (Instance, MsgWindow, NULL);
666 
667  // if an error occurred, try again with billsock
668  if (err != 0) {
669    // get the path of billsock (current directory + ("net16" | "net32"))
670    char winsockpath[1024]; // HARD LIMIT!!!!
671   
672    find_location();
673    char *data_location_c = data_location.getcstr();
674    strcpy (winsockpath, data_location_c);
675    delete []data_location_c;
676   
677    // remove all the slashes at the end of billpath
678    int len = strlen (winsockpath);
679    while ((len > 0) && ((winsockpath[len-1] == '\\') || (winsockpath[len-1] == '/'))) {
680      --len;
681    }
682    winsockpath[len] = '\0';
683   
684    if (osver.dwPlatformId == VER_PLATFORM_WIN32s)
685      strcat (winsockpath, "\\net16\\");
686    else {
687      strcat (winsockpath, "\\net32\\");
688      strcpy (startbrowserdir, winsockpath);
689    }
690   
691    // try again
692    err = tryinitnetwork (Instance, MsgWindow, winsockpath);
693   
694    if (err == 0) {
695      // we will need to use netscape on 95/98/NT machines
696      if (osver.dwPlatformId != VER_PLATFORM_WIN32s) {
697    netscapeneeded = 1;
698    // make sure the browser state is in step with the network condition
699    gsdl_check_browser_settings (netscapeneeded);
700      }
701     
702      // check to see if a browser is running
703      if (browserrunning(gsdl_browser_exe) == NO_ERROR) {
704    MessageBox (NULL,
705            "The Greenstone Digital Library software has detected a\n"
706            "running browser. To let our networking software\n"
707            "correctly initialize, please shut down your browser\n"
708            "and restart the Greenstone Digital Library software.",
709            "Greenstone Digital Library Software", MB_OK|MB_APPLMODAL);
710    PostMessage(MsgWindow,WM_CLOSE,0,0);
711    finish_up(false); // will unload winsock
712    exit(0);      // nothing more to do
713      }
714    }
715  }
716 
717  // if an error occurred display a nice error message
718  if (err != 0) {
719   
720    // WSASYSNOTREADY   Couldn't load winsock
721    // WSAVERNOTSUPPORTED   The version of Windows Sockets support requested
722    //          is not provided by this particular Windows Sockets implementation.
723    // WSAEINVAL    The Windows Sockets version specified by the application
724    //          is not supported by this DLL.
725    // WSAEPROTONOSUPPORT   The specified protocol is not supported.
726    // WSAEPROTOTYPE    The specified protocol is the wrong type for this socket.
727    // WSAESOCKTNOSUPPORT   The specified socket type is not supported in
728    //      this address family.
729    // WSANOTINITIALISED    A successful WSAStartup must occur before
730    //      using this function.
731    // WSAENETDOWN  The Windows Sockets implementation
732    //      has detected that the network subsystem has failed.
733    // WSAEADDRINUSE    The specified address
734    //      is already in use. (See the SO_REUSEADDR socket option under setsockopt.)
735    // WSAEFAULT    The namelen argument is too small (less
736    //      than the size of a struct sockaddr).
737    // WSAEINPROGRESS   A blocking Windows Sockets call is in progress.
738    // WSAEAFNOSUPPORT  The specified address family is not supported
739    //      by this protocol.
740    // WSAENOBUFS   Not enough buffers available, too many connections.
741    // WSAENOTSOCK  The descriptor is not a socket.
742    // WSAEISCONN   The socket is already connected.
743    // WSAEMFILE    No more file descriptors are available.
744    // WSAEOPNOTSUPP    The referenced socket is not of a type that
745    //      supports the listen operation.
746   
747    // get a text version of the error number
748    char errstr[256];
749   
750    switch (err) {
751    case WSASYSNOTREADY: strcpy(errstr, "WSASYSNOTREADY");
752      break;
753    case WSAVERNOTSUPPORTED: strcpy (errstr, "WSAVERNOTSUPPORTED");
754      break;
755    case WSAEINVAL: strcpy (errstr, "WSAEINVAL");
756      break;
757    case WSAEPROTONOSUPPORT: strcpy (errstr, "WSAEPROTONOSUPPORT");
758      break;
759    case WSAEPROTOTYPE: strcpy (errstr, "WSAEPROTOTYPE");
760      break;
761    case WSAESOCKTNOSUPPORT: strcpy (errstr, "WSAESOCKTNOSUPPORT");
762      break;
763    case WSANOTINITIALISED: strcpy (errstr, "WSANOTINITIALISED");
764      break;
765    case WSAEFAULT: strcpy (errstr, "WSAEFAULT");
766      break;
767    case WSAEAFNOSUPPORT: strcpy (errstr, "WSAEAFNOSUPPORT");
768      break;
769    case WSAENOTSOCK: strcpy (errstr, "WSAENOTSOCK");
770      break;
771    case WSAEISCONN: strcpy (errstr, "WSAEISCONN");
772      break;
773    case WSAEOPNOTSUPP: strcpy (errstr, "WSAEOPNOTSUPP");
774      break;
775    case WSAENETDOWN: strcpy (errstr, "WSAENETDOWN");
776      break;
777    case WSAEADDRINUSE: strcpy (errstr, "WSAEADDRINUSE");
778      break;
779    case WSAEINPROGRESS: strcpy (errstr, "WSAEINPROGRESS");
780      break;
781    case WSAENOBUFS: strcpy (errstr, "WSAENOBUFS");
782      break;
783    case WSAEMFILE: strcpy (errstr, "WSAEMFILE");
784      break;
785    default: sprintf (errstr, "WSA ERROR: %i", err);
786      break;
787    }
788   
789    // create a nice error message
790    char message[2048];
791   
792    switch (err) {
793    case WSAEADDRINUSE:
794      // couldn't bind socket
795      sprintf (message, "Could not find a free socket.", errstr);
796      break;
797     
798    default:
799      // cannot init winsock
800      sprintf (message, "Could not initialize the network\n"
801           " (Reason: %s).", errstr);
802      break;
803    }
804   
805    strcat (message, "\n\n"
806        "Please submit a bug report using the support.htm file\n"
807        "on the CD-ROM.");
808   
809    MessageBox (NULL, message, "Greenstone Digital Library Software", MB_OK);
810  }
811 
812  return (err == 0);
813}
814
815
816void log_computer_info () {
817  char tmpstr[1024];
818 
819  // get various information about this computer
820  if (gsdl_keep_log || gsdl_show_console) {
821    // get operating system information
822    OSVERSIONINFO osver;
823    osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
824   
825    if (GetVersionEx(&osver)) {
826      if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
827    log_message ("Platform: win32s\n");
828      } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
829    log_message ("Platform: windows 95\n");
830      } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
831    log_message ("Platform: windows NT\n");
832      }
833     
834      sprintf (tmpstr, "MajorVersion: %i\n", (int)osver.dwMajorVersion);
835      log_message(tmpstr);
836      sprintf (tmpstr, "MinorVersion: %i\n", (int)osver.dwMinorVersion);
837      log_message(tmpstr);
838      sprintf (tmpstr, "BuildNumber: %i\n", (int)osver.dwBuildNumber);
839      log_message(tmpstr);
840      sprintf (tmpstr, "CSDVersion: %s\n\n", osver.szCSDVersion);
841      log_message(tmpstr);
842    }
843   
844    // get memory information
845    MEMORYSTATUS memstatus;
846    memstatus.dwLength = sizeof(MEMORYSTATUS);
847    GlobalMemoryStatus(&memstatus);
848   
849    sprintf (tmpstr, "TotalPhys: %i Meg\n", (int)(memstatus.dwTotalPhys/1024/1024));
850    log_message (tmpstr);
851    sprintf (tmpstr, "AvailPhys: %i Meg\n", (int)(memstatus.dwAvailPhys/1024/1024));
852    log_message (tmpstr);
853    sprintf (tmpstr, "TotalPageFile: %i Meg\n", (int)(memstatus.dwTotalPageFile/1024/1024));
854    log_message (tmpstr);
855    sprintf (tmpstr, "AvailPageFile: %i Meg\n", (int)(memstatus.dwAvailPageFile/1024/1024));
856    log_message (tmpstr);
857    sprintf (tmpstr, "TotalVirtual: %i Meg\n", (int)(memstatus.dwTotalVirtual/1024/1024));
858    log_message (tmpstr);
859    sprintf (tmpstr, "AvailVirtual: %i Meg\n\n", (int)(memstatus.dwAvailVirtual/1024/1024));
860    log_message (tmpstr);
861   
862    // log the version number
863    log_message("GSDL version: " GSDL_VERSION "\n");
864  }
865 
866}
867
868// possible command line options are
869// --location=directory (the path to GSDLHOME which defaults to the
870// directory where server.exe lives)
871// --config=file (the path to the configuration file to use which defaults
872// to GSDLHOME\llssite.cfg)
873// --cmd=init  Used to initialize the llssite.cfg file only - jmt12 18/11/2003
874static void parse_args(const text_t cmdline, text_t &location, text_t &config_file, text_t &command) {
875
876  location.clear();
877  config_file.clear();
878  command.clear(); // jmt12 18/11/2003
879
880  if (cmdline.size() < 3) return;
881
882  text_t name, val;
883  bool foundname = false;
884  text_t::const_iterator here = cmdline.begin();
885  text_t::const_iterator end = cmdline.end();
886  while (here != end) {
887    if (*here == '-' && ((here+1) != end) && (*(here+1) == '-')) {
888      ++here;
889      if (name == "location") {
890    location = val;
891      } else if (name == "config") {
892    config_file = val;
893      } else if(name == "cmd") { // jmt12 18/11/2003
894    command = val;
895      }
896      foundname = false;
897      name.clear();
898      val.clear();
899    } else if (*here == '=') {
900      foundname = true;
901    } else {
902      if (foundname) {
903    val.push_back(*here);
904      } else {
905    name.push_back(*here);
906      }
907    }
908    ++here;
909  }
910  if (name == "location") {
911    location = val;
912  } else if (name == "config") {
913    config_file = val;
914  } else if(name == "cmd") { // jmt12 18/11/2003
915    command = val;
916  }
917}
918
919
920// Tries to generate llssite.cfg from llssite.cfg.in in directory given
921// by location variable (assumes location is GSDLHOME), if llsite.cfg is missing
922void ensure_llssite_cfg(const text_t location) {
923  text_t configfile = location+"\llssite.cfg";
924  text_t configtemplate = location+"\llssite.cfg.in";
925
926  if(!file_exists (configfile)) {
927   
928    if(file_exists (configtemplate)) {
929      // try creating llssite.cfg from the template configfile llssite.cfg.in
930      // by using a straightforward copy
931      file_copy(configtemplate, configfile);
932    }
933  }
934}
935
936
937// Added code to allow for an 'init' run of the server which just creates the llssite.cfg file
938int __stdcall WinMain(HINSTANCE Instance, HINSTANCE /*PrevInstance*/, LPSTR CmdLineStr, int /*CmdShow*/) {
939  HWND MainWindow;  MSG Message;  WNDCLASS MainClass; 
940
941  // One instance of the local library server is quite enough, thank you very much
942  HWND gw = FindWindow("Greenstone Digital Library Software",
943               "Greenstone Digital Library Software");
944  if (gw != NULL) {
945    exit(1);
946  }
947
948  // parse arguments
949  text_t location, config_file, command;
950  parse_args(CmdLineStr, location, config_file, command);
951  gsdl_conffile = config_file;
952 
953  // Try to generate the llssite.cfg file if it's missing
954  ensure_llssite_cfg(location);
955
956  // jmt12 18/11/2003
957  if(command == "init") {
958    // init various modules
959    read_settings(0); // don't know if netscape is needed at this point
960    finish_up(true);
961    exit(0);
962  }
963
964  //Create a window class
965  MainClass.style = CS_HREDRAW | CS_VREDRAW;
966  MainClass.lpfnWndProc = WndProc;
967  MainClass.cbClsExtra = 0;
968  MainClass.cbWndExtra = 0;
969  MainClass.hInstance = Instance;
970  MainClass.hIcon     = LoadIcon(Instance, MAKEINTRESOURCE(TRAY_ICON));
971  MainClass.hCursor   = LoadCursor(NULL, IDC_ARROW);
972  MainClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
973  MainClass.lpszMenuName = MAKEINTRESOURCE(Main_Menu);
974  MainClass.lpszClassName = "Greenstone Digital Library Software";
975  if (!RegisterClass(&MainClass))
976    return 0;
977 
978 
979  // Load various bitmaps
980  coltitlebitmap = LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_COL_TITLE));
981  logobitmap= LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_LOGO));
982 
983  // Create the main window
984  MainWindow = CreateWindow("Greenstone Digital Library Software",
985                "Greenstone Digital Library Software",
986                WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
987                WS_MINIMIZEBOX,
988                CW_USEDEFAULT, CW_USEDEFAULT,
989                MAINWINDOWWIDTH + WASTEWIDTH,
990                MAINWINDOWHEIGHT + WASTEHEIGHT,
991                NULL, NULL, Instance, NULL);
992 
993  text_rect.left = 0; 
994  text_rect.top = VERSIONY+VERSIONHEIGHT + 5;
995  text_rect.right = MAINWINDOWWIDTH;
996  text_rect.bottom = LOGOY-SPACERWIDTH;
997 
998  window_state = undefined_window;
999 
1000  ShowWindow(MainWindow, SW_SHOW);
1001  set_location(location);
1002 
1003  // get ready to draw the main window
1004  RECT windowRect;
1005  GetClientRect (MainWindow, &windowRect);
1006  HDC pdc = GetDC (MainWindow);
1007 
1008  // retrieve and save the text metrics
1009  TEXTMETRIC tm;
1010  GetTextMetrics(pdc, &tm);
1011  line_spacing = tm.tmHeight + tm.tmExternalLeading;
1012  GSDL_Window = MainWindow; 
1013
1014  // init various modules
1015  read_settings (0); // don't know if netscape is needed at this point
1016 
1017  if (!gsdl_auto_enter) {
1018   
1019    // add the select version checkbox
1020    Enter = CreateWindow("BUTTON",             // predefined class
1021             "Enter Library",      // button text
1022             WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_DEFPUSHBUTTON,  // styles
1023             ENTERBUTTONX,         // starting x position
1024             ENTERBUTTONY,         // starting y position
1025             ENTERBUTTONWIDTH,     // button width
1026             ENTERBUTTONHEIGHT,    // button height
1027             MainWindow,           // parent window
1028             NULL,                 // No menu
1029             Instance,
1030             NULL);                // pointer not needed
1031   
1032//      EnterRestricted = CreateWindow("Button",                // predefined class
1033//                     "Restricted Version",    // button text
1034//                     WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_PUSHBUTTON,   // styles
1035//                     ALTERNATIVEBUTTONX,      // starting x position
1036//                     ALTERNATIVEBUTTONY,      // starting y position
1037//                     ALTERNATIVEBUTTONWIDTH-(INFOBUTTONWIDTH+SPACERWIDTH),  // button width
1038//                     ALTERNATIVEBUTTONHEIGHT, // button height
1039//                     MainWindow,              // parent window
1040//                     (HMENU)NULL,             // No menu
1041//                     Instance,
1042//                     NULL);                   // pointer not needed
1043   
1044//      InfoRestricted = CreateWindow("Button",                // predefined class
1045//                    NULL,
1046//                    WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_BITMAP,   // styles
1047//                    ALTERNATIVEBUTTONWIDTH-INFOBUTTONWIDTH+SPACERWIDTH, // starting x position
1048//                    ALTERNATIVEBUTTONY,      // starting y position
1049//                    INFOBUTTONWIDTH,         // button width
1050//                    ALTERNATIVEBUTTONHEIGHT, // button height
1051//                    MainWindow,              // parent window
1052//                    (HMENU)NULL,             // No menu
1053//                    Instance,
1054//                    NULL);                   // pointer not needed
1055   
1056//      HANDLE i_icon = LoadImage (Instance, MAKEINTRESOURCE(GSDL_ICBMP), IMAGE_BITMAP,
1057//                     INFOBUTTONWIDTH-4, ALTERNATIVEBUTTONHEIGHT-4, LR_DEFAULTCOLOR);
1058//      SendMessage (InfoRestricted, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)i_icon);
1059   
1060    SetFocus (Enter);
1061       
1062    // Since we have not entered the library yet, set the URL in the configfile to pending state
1063    gsdl_url = "URL_pending";
1064    write_settings(gsdl_url);
1065
1066    enterstring = strenterlib;
1067    paint_window (pdc, windowRect);
1068   
1069    // message loop for init buttons
1070    while (!init_done) {
1071      if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1072    if (Message.message == WM_QUIT) return Message.wParam;
1073    if (!IsDialogMessage (MainWindow, &Message)) {
1074      TranslateMessage(&Message); /* translate keyboard messages */
1075      DispatchMessage(&Message);  /* return control to Windows NT */
1076    }
1077      } else {
1078    Sleep (1);
1079      }
1080    }
1081   
1082    // don't want these buttons anymore
1083    DestroyWindow (Enter);
1084    // DestroyWindow (EnterRestricted);
1085    // DestroyWindow (InfoRestricted);
1086   
1087    enterstring = strnothing;
1088    paint_window (pdc, windowRect);
1089   
1090  } else {
1091    // auto enter is enabled - start up standard version
1092    init_type = 1;
1093    init_done = 1;
1094  }
1095 
1096  // draw the main window containing an init message
1097  infostring = strinit;
1098  paint_window (pdc, windowRect);
1099  DWORD lastcheck = GetTickCount();
1100 
1101  have_networking = initnetwork (Instance, MainWindow);
1102  if (!have_networking) {
1103    MessageBox(NULL,
1104           "Failed to initialize networking.",
1105           "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1106    exit (0);
1107  }
1108
1109  if (!gsdl_init()) // quit if can't initialise the library correctly
1110    exit (0);
1111  initstartbrowser();
1112  log_computer_info ();
1113 
1114  // show the initialising message for at least 1 second
1115  while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) {
1116    Sleep (1);
1117  }
1118 
1119  // attempt to start a browser
1120  if (gsdl_show_console || !gsdl_start_browser) infostring = strnothing;
1121  else infostring = strsb;
1122  paint_window (pdc, windowRect);
1123  lastcheck = GetTickCount();
1124  if (enter_library (MainWindow) && !gsdl_show_console) {
1125    // stay maximised for at least 1 second
1126    while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) Sleep (1);
1127    ShowWindow(MainWindow,SW_MINIMIZE);
1128  }
1129 
1130  // add the "restart library" button
1131  GoButton = CreateWindow("BUTTON",              // predefined class
1132              "Restart Library",     // button text
1133              WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // styles
1134              RESTARTBUTTONX,        // starting x position
1135              RESTARTBUTTONY,        // starting y position
1136              RESTARTBUTTONWIDTH,    // button width
1137              RESTARTBUTTONHEIGHT,   // button height
1138              MainWindow,            // parent window
1139              NULL,                  // No menu
1140              Instance,
1141              NULL);                 // pointer not needed
1142 
1143  infostring = strrestartlib;
1144  paint_window (pdc, windowRect);
1145 
1146  // release the DC used to display the init messages
1147  ReleaseDC (MainWindow, pdc);
1148 
1149  //Message loop
1150  lastcheck = GetTickCount();
1151  int seenbrowser = 0;  // if we see a browser then it disappears
1152                        // we will ask if they want to close the
1153                        // the library down
1154  char last_gsdl_browser_exe[MAX_FILENAME_SIZE]; // need to notice when the
1155                                                 // browser setting changes
1156  strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1157 
1158  for (;;) {
1159    if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1160      if (Message.message == WM_QUIT) break;
1161      if (!IsDialogMessage (MainWindow, &Message)) {
1162    TranslateMessage(&Message); /* translate keyboard messages */
1163    DispatchMessage(&Message);  /* return control to Windows NT */
1164      }
1165     
1166    } else {
1167      if (DiffTickCounts (lastcheck, GetTickCount()) > 500) {
1168    // make sure the browser hasn't changed
1169    if (strcmp (last_gsdl_browser_exe, gsdl_browser_exe) != 0) {
1170      seenbrowser = 0;
1171      strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1172    }
1173   
1174    // do check
1175    lastcheck = GetTickCount();
1176    if (gsdl_start_browser && browserrunning(gsdl_browser_exe) == NO_ERROR) {
1177      // we were able to connect to a browser
1178      seenbrowser = 1;
1179     
1180      // see if the enter library button has been pressed
1181      // with nothing happening for 20 seconds
1182      if ((enterlib_libaccessnum >= 0) &&
1183          (enterlib_libaccessnum == libaccessnum) &&
1184          (DiffTickCounts (enterlib_time, GetTickCount()) > 20000)) {
1185        // something could be wrong!! (most likely cause is a proxy)
1186        MessageBox(NULL,
1187               "Your browser does not seem to be responding to the 'Enter Library'\n"
1188               "request. Try turning off all proxy servers in your browser settings.\n"
1189               "If you are using Internet Explorer make sure BOTH dialup settings\n"
1190               "AND LAN settings have their proxy servers disabled.",
1191               "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1192        enterlib_libaccessnum = -1;
1193      }
1194     
1195     
1196    } else {
1197      // no browser was found
1198     
1199      if (seenbrowser) {
1200        // we have seen a browser in the past
1201        if (MessageBox(NULL,
1202               "The Greenstone Digital Library software has noticed that you\n"
1203               "shut down your browser. Would you also like to shut down the\n"
1204               "Greenstone Digital Library software?",
1205               "Greenstone Digital Library Software",MB_YESNO|MB_SYSTEMMODAL) == IDYES)
1206          PostMessage(MainWindow,WM_CLOSE,0,0);
1207      }
1208      seenbrowser = 0;
1209    }
1210      }
1211     
1212      Sleep (1); // millisecond
1213    }
1214  }
1215 
1216  return Message.wParam;
1217}
1218
Note: See TracBrowser for help on using the browser.