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

Revision 19514, 37.6 KB (checked in by ak19, 10 years ago)

Reverting changes made to allow GLI to cope with GSI being launched independently (w32server writes out URL_pending to llssite.cfg).

  • 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
341    DWORD local_ip = GetLocalIP();
342    if (local_ip == INADDR_ANY || gsdl_address_resolution_method == 3) {
343      local_ip = 127 + (0 << 8) + (0 << 16) + (1 << 24);
344    }
345
346    if (gsdl_address_resolution_method == 1 || gsdl_address_resolution_method == 3) {
347      sprintf(gsdl_address, "%d.%d.%d.%d", local_ip & 0xFF, (local_ip >> 8) & 0xFF, (local_ip >> 16) & 0xFF, (local_ip >> 24) & 0xFF);
348    }
349    else if (gsdl_address_resolution_method == 2) {
350      sprintf(gsdl_address, "localhost");
351    }
352    else {
353      strcpy(gsdl_address, GetLocalName(NULL));
354    }
355
356    text_t url = "http://" + text_t(gsdl_address);
357
358    gsdl_url = url;
359    write_settings(gsdl_url);
360
361    if (gsdl_port_num != 80)
362      url += ":" + text_t(gsdl_port_num);
363
364    url += gsdl_enterlib;
365
366    // add a unique ending so it will always result in a request
367    text_t::const_iterator it =
368      findchar (gsdl_enterlib.begin(), gsdl_enterlib.end(), '?');
369    if (it == gsdl_enterlib.end()) url.push_back ('?');
370    else url.push_back ('&');
371    int tcount = GetTickCount();
372    url += "uq=" + text_t(tcount);
373   
374    // remember the library access number for later proxy checking
375    enterlib_libaccessnum = libaccessnum;
376   
377    if (gsdl_start_browser) {
378
379      // do a quick check to make sure we're using netscape when
380      // we should be (it might have been just installed)
381      if (netscapeneeded) gsdl_check_browser_settings (netscapeneeded);
382   
383      char *cstr_url = url.getcstr();
384      if (strlen (startbrowserdir) <= 0) {
385    res = startbrowser (cstr_url, gsdl_browser_exe, NULL);
386   
387      } else res = startbrowser (cstr_url, gsdl_browser_exe, startbrowserdir);
388   
389      delete []cstr_url;
390
391    } else {
392      return 1;
393    }
394  }
395 
396  if (res == SB_NOERROR) {
397    // success !!
398   
399    // remember the time the browser was started for later proxy checking
400    if (have_networking) enterlib_time = GetTickCount();
401   
402    return 1;
403  }
404 
405  // no browser was started
406  enterlib_libaccessnum = -1;
407 
408  if ((res == SB_FAIL_BADFORMAT) || (res == SB_FAIL_NOTFOUND)) {
409    if (!netscapeneeded) { // any browser
410      MessageBox(Window,
411         "Failed to start your chosen browser. It seems that your\n"
412         "chosen browser has been removed or corrupted.\n"
413         "Please check your browser choice by going to the\n"
414         "'Settings...' item under the 'File' menu.",
415         "Greenstone Digital Library Software", MB_OK);
416    } else { // netscape used
417      MessageBox(Window,
418         "Failed to start Netscape. It seems that Netscape has\n"
419         "been removed or corrupted. You need Netscape\n"
420         "installed to use the Greenstone Digital Library\n"
421         "software on non-networked machines.",
422         "Greenstone Digital Library Software", MB_OK);
423    }
424   
425  } else {
426    MessageBox(Window,
427           "Failed to start your browser. This may have been\n"
428           "because there was not enough memory available. Shut\n"
429           "down all other applications you have running, and\n"
430           "try again.",
431           "Greenstone Digital Library Software", MB_OK);
432  }
433 
434  return 0; // failed
435}
436
437
438void install_netscape (HWND Window) {
439  char installpath[256];
440 
441  // try to find the browser directory
442  char *gsdlhome = gsdl_gsdlhome.getcstr();
443  strcpy (installpath, gsdlhome); // use gsdlhome to find the CD-ROM drive...
444  delete []gsdlhome;
445 
446  // remove any slashes from the pathname
447  int len = strlen (installpath);
448  while ((len > 0) && ((installpath[len-1] == '\\') || (installpath[len-1] == '/'))) {
449    --len;
450  }
451  // remove '\gsdl'
452  len = len - 5;
453  installpath[len] = '\0';
454 
455  strcat (installpath, "\\netscape\\");
456 
457  // check this directory
458  if (!cstrcheckdir(installpath)) {
459    return;
460  }
461 
462  // get the operating system information
463  OSVERSIONINFO osver;
464  memset(&osver, 0, sizeof(OSVERSIONINFO));
465  osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
466  GetVersionEx(&osver);
467
468  // get the install program for this operating system
469  if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
470    strcat (installpath, "n16e405.exe");
471  } else {
472    strcat (installpath, "n32e405.exe");
473  }
474 
475  // run the install program
476  int res = WinExec (installpath, SW_SHOW);
477  if (res == 0) {
478    // out of resources or memory
479    MessageBox (Window,
480        "Did not have enough resources or memory to run the\n"
481        "install program. Try shutting down all other programs\n"
482        "and trying again.",
483        "Greenstone Digital Library Software",
484        MB_OK|MB_APPLMODAL);
485   
486  } else if (res == ERROR_BAD_FORMAT) {
487    // executable image is corrupt -- ????
488    MessageBox (Window,
489        "The install program seems to be corrupt.",
490        "Greenstone Digital Library Software",
491        MB_OK|MB_APPLMODAL);
492   
493  } else if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_PATH_NOT_FOUND)) {
494    // couldn't find the executable -- ????
495    MessageBox (Window,
496        "Could not find the install program. Try installing\n"
497        "Netscape from the Greenstone Digital Library\n"
498        "software's install program.",
499        "Greenstone Digital Library Software",
500        MB_OK|MB_APPLMODAL);
501  }
502}
503
504void open_help () {
505  char topdir[256], cmd[256];
506 
507  // try to find the browser directory
508  char *gsdlhome = gsdl_gsdlhome.getcstr();
509  strcpy (topdir, gsdlhome); // use gsdlhome to find the CD-ROM drive...
510  delete []gsdlhome;
511  strcpy (cmd, "notepad ");
512 
513  // remove any slashes from the pathname
514  int len = strlen (topdir);
515  while ((len > 0) && ((topdir[len-1] == '\\') || (topdir[len-1] == '/'))) {
516    --len;
517  }
518  // remove the '\gsdl'
519  len = len - 5;
520  topdir[len] = '\0';
521
522  strcat (topdir, "\\README.txt");
523  strcat (cmd, topdir);
524 
525  WinExec (cmd, SW_SHOW);
526}
527
528
529long __stdcall WndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam) {
530  switch(Message) {
531    // Constant Messages
532  case WM_CREATE:
533    break;
534   
535  case WM_COMMAND:
536    if ((GoButton != NULL) && ((HWND)LParam == GoButton)) {
537      // attempt to start a browser
538      gsdl_start_browser = 1;
539      if (enter_library (Window) && !gsdl_show_console)
540        ShowWindow(Window,SW_MINIMIZE);
541
542    } else if ((Enter != NULL) && ((HWND)LParam == Enter)) {
543      init_done = 1;
544      init_type = 1;
545
546//      } else if ((EnterRestricted != NULL) && ((HWND)LParam == EnterRestricted)) {
547//        init_done = 1;
548//        init_type = 0;
549
550//      } else if ((InfoRestricted != NULL) && ((HWND)LParam == InfoRestricted)) {
551//        MessageBox (NULL, "The Greenstone system automatically determines whether your computer has\n"
552//            "network software installed or is connected to a network.  It operates correctly\n"
553//            "under any of these conditions.\n\n"
554//            "The restricted version is intended for use when the standard one\n\n"
555//            "   (a) causes an unwanted telephone dialup operation;\n"
556//            "   (b) fails to run because network software is installed, but installed\n"
557//            "         incorrectly.\n\n"
558//            "The restricted version only works with Netscape (not Internet Explorer).\n\n"
559//            "Unless these problems arise, you should always use the standard version\n"
560//            "(press the 'Enter Library' button).\n",
561//            "Greenstone Digital Library Software",
562//            MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
563
564    } else {
565      switch (LOWORD(WParam)) {
566      case ID_PROJECT_SETTINGS:
567    Settings_Dialog(Window, netscapeneeded);
568    break;
569      case ID_INSTALL_NETSCAPE:
570    install_netscape(Window);
571    break;
572      case IDHELP:
573    open_help();
574    break;
575      case ID_PROJECT_EXIT:
576        finish_up(false);
577        break;
578      default:
579        break;
580      }
581    }
582    break;
583   
584  case WM_PAINT:
585    handle_painting(Window);
586    break;
587   
588  case HTTP_SERVER_MSG:
589    ProcessHTTPServerMsg(WParam, LParam);
590    break;
591   
592  case WM_DESTROY:
593    finish_up(false);
594    break;
595   
596  default:
597    //Unhandled Messages end up here (DefWindowProc)
598    return DefWindowProc(Window, Message, WParam, LParam);
599  }
600 
601  return(0);
602}
603
604// returns 0 if successful,
605// otherwise a WSA error number
606int tryinitnetwork (HANDLE Instance, HWND MsgWindow, char *path) {
607  // try to load winsock
608  int err = d_LoadWinsock (path);
609 
610  if (err == D_NOERROR) {
611    // next, try to init netio
612    err = InitNetIO();
613   
614    if (err == 0) {
615      // next, try to start the http server
616      err = StartHTTPServer(MsgWindow);
617     
618      if (err == 0) {
619    // finally, get the host name (no error value
620    // is returned from this function)
621    GetLocalName((HINSTANCE)Instance);
622   
623      } else {
624    // couldn't start the http server,
625    // deinit netio and unload winsock
626    CleanUpNetIO();
627    d_UnloadWinsock();
628      }
629     
630    } else {
631      // couldn't init netio, unload winsock
632      d_UnloadWinsock();
633    }
634   
635  } else {
636    // couldn't load winsock
637    err = WSASYSNOTREADY;
638  }
639 
640  return err;
641}
642
643
644// inits all the network functionality
645// returns 0 if an unrecoverable error occurred,
646// and 1 if everything successfully initialised.
647int initnetwork (HANDLE Instance, HWND MsgWindow) {
648  OSVERSIONINFO osver;
649 
650  // get the operating system information
651  memset(&osver, 0, sizeof(OSVERSIONINFO));
652  osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
653  GetVersionEx(&osver);
654 
655  // first try to initialise the network with system installed
656  // networking software
657  startbrowserdir[0] = '\0';
658  netscapeneeded = 0;
659  int err = 1;
660  if (init_type == 1) err = tryinitnetwork (Instance, MsgWindow, NULL);
661 
662  // if an error occurred, try again with billsock
663  if (err != 0) {
664    // get the path of billsock (current directory + ("net16" | "net32"))
665    char winsockpath[1024]; // HARD LIMIT!!!!
666   
667    find_location();
668    char *data_location_c = data_location.getcstr();
669    strcpy (winsockpath, data_location_c);
670    delete []data_location_c;
671   
672    // remove all the slashes at the end of billpath
673    int len = strlen (winsockpath);
674    while ((len > 0) && ((winsockpath[len-1] == '\\') || (winsockpath[len-1] == '/'))) {
675      --len;
676    }
677    winsockpath[len] = '\0';
678   
679    if (osver.dwPlatformId == VER_PLATFORM_WIN32s)
680      strcat (winsockpath, "\\net16\\");
681    else {
682      strcat (winsockpath, "\\net32\\");
683      strcpy (startbrowserdir, winsockpath);
684    }
685   
686    // try again
687    err = tryinitnetwork (Instance, MsgWindow, winsockpath);
688   
689    if (err == 0) {
690      // we will need to use netscape on 95/98/NT machines
691      if (osver.dwPlatformId != VER_PLATFORM_WIN32s) {
692    netscapeneeded = 1;
693    // make sure the browser state is in step with the network condition
694    gsdl_check_browser_settings (netscapeneeded);
695      }
696     
697      // check to see if a browser is running
698      if (browserrunning(gsdl_browser_exe) == NO_ERROR) {
699    MessageBox (NULL,
700            "The Greenstone Digital Library software has detected a\n"
701            "running browser. To let our networking software\n"
702            "correctly initialize, please shut down your browser\n"
703            "and restart the Greenstone Digital Library software.",
704            "Greenstone Digital Library Software", MB_OK|MB_APPLMODAL);
705    PostMessage(MsgWindow,WM_CLOSE,0,0);
706    finish_up(false); // will unload winsock
707    exit(0);      // nothing more to do
708      }
709    }
710  }
711 
712  // if an error occurred display a nice error message
713  if (err != 0) {
714   
715    // WSASYSNOTREADY   Couldn't load winsock
716    // WSAVERNOTSUPPORTED   The version of Windows Sockets support requested
717    //          is not provided by this particular Windows Sockets implementation.
718    // WSAEINVAL    The Windows Sockets version specified by the application
719    //          is not supported by this DLL.
720    // WSAEPROTONOSUPPORT   The specified protocol is not supported.
721    // WSAEPROTOTYPE    The specified protocol is the wrong type for this socket.
722    // WSAESOCKTNOSUPPORT   The specified socket type is not supported in
723    //      this address family.
724    // WSANOTINITIALISED    A successful WSAStartup must occur before
725    //      using this function.
726    // WSAENETDOWN  The Windows Sockets implementation
727    //      has detected that the network subsystem has failed.
728    // WSAEADDRINUSE    The specified address
729    //      is already in use. (See the SO_REUSEADDR socket option under setsockopt.)
730    // WSAEFAULT    The namelen argument is too small (less
731    //      than the size of a struct sockaddr).
732    // WSAEINPROGRESS   A blocking Windows Sockets call is in progress.
733    // WSAEAFNOSUPPORT  The specified address family is not supported
734    //      by this protocol.
735    // WSAENOBUFS   Not enough buffers available, too many connections.
736    // WSAENOTSOCK  The descriptor is not a socket.
737    // WSAEISCONN   The socket is already connected.
738    // WSAEMFILE    No more file descriptors are available.
739    // WSAEOPNOTSUPP    The referenced socket is not of a type that
740    //      supports the listen operation.
741   
742    // get a text version of the error number
743    char errstr[256];
744   
745    switch (err) {
746    case WSASYSNOTREADY: strcpy(errstr, "WSASYSNOTREADY");
747      break;
748    case WSAVERNOTSUPPORTED: strcpy (errstr, "WSAVERNOTSUPPORTED");
749      break;
750    case WSAEINVAL: strcpy (errstr, "WSAEINVAL");
751      break;
752    case WSAEPROTONOSUPPORT: strcpy (errstr, "WSAEPROTONOSUPPORT");
753      break;
754    case WSAEPROTOTYPE: strcpy (errstr, "WSAEPROTOTYPE");
755      break;
756    case WSAESOCKTNOSUPPORT: strcpy (errstr, "WSAESOCKTNOSUPPORT");
757      break;
758    case WSANOTINITIALISED: strcpy (errstr, "WSANOTINITIALISED");
759      break;
760    case WSAEFAULT: strcpy (errstr, "WSAEFAULT");
761      break;
762    case WSAEAFNOSUPPORT: strcpy (errstr, "WSAEAFNOSUPPORT");
763      break;
764    case WSAENOTSOCK: strcpy (errstr, "WSAENOTSOCK");
765      break;
766    case WSAEISCONN: strcpy (errstr, "WSAEISCONN");
767      break;
768    case WSAEOPNOTSUPP: strcpy (errstr, "WSAEOPNOTSUPP");
769      break;
770    case WSAENETDOWN: strcpy (errstr, "WSAENETDOWN");
771      break;
772    case WSAEADDRINUSE: strcpy (errstr, "WSAEADDRINUSE");
773      break;
774    case WSAEINPROGRESS: strcpy (errstr, "WSAEINPROGRESS");
775      break;
776    case WSAENOBUFS: strcpy (errstr, "WSAENOBUFS");
777      break;
778    case WSAEMFILE: strcpy (errstr, "WSAEMFILE");
779      break;
780    default: sprintf (errstr, "WSA ERROR: %i", err);
781      break;
782    }
783   
784    // create a nice error message
785    char message[2048];
786   
787    switch (err) {
788    case WSAEADDRINUSE:
789      // couldn't bind socket
790      sprintf (message, "Could not find a free socket.", errstr);
791      break;
792     
793    default:
794      // cannot init winsock
795      sprintf (message, "Could not initialize the network\n"
796           " (Reason: %s).", errstr);
797      break;
798    }
799   
800    strcat (message, "\n\n"
801        "Please submit a bug report using the support.htm file\n"
802        "on the CD-ROM.");
803   
804    MessageBox (NULL, message, "Greenstone Digital Library Software", MB_OK);
805  }
806 
807  return (err == 0);
808}
809
810
811void log_computer_info () {
812  char tmpstr[1024];
813 
814  // get various information about this computer
815  if (gsdl_keep_log || gsdl_show_console) {
816    // get operating system information
817    OSVERSIONINFO osver;
818    osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
819   
820    if (GetVersionEx(&osver)) {
821      if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
822    log_message ("Platform: win32s\n");
823      } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
824    log_message ("Platform: windows 95\n");
825      } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
826    log_message ("Platform: windows NT\n");
827      }
828     
829      sprintf (tmpstr, "MajorVersion: %i\n", (int)osver.dwMajorVersion);
830      log_message(tmpstr);
831      sprintf (tmpstr, "MinorVersion: %i\n", (int)osver.dwMinorVersion);
832      log_message(tmpstr);
833      sprintf (tmpstr, "BuildNumber: %i\n", (int)osver.dwBuildNumber);
834      log_message(tmpstr);
835      sprintf (tmpstr, "CSDVersion: %s\n\n", osver.szCSDVersion);
836      log_message(tmpstr);
837    }
838   
839    // get memory information
840    MEMORYSTATUS memstatus;
841    memstatus.dwLength = sizeof(MEMORYSTATUS);
842    GlobalMemoryStatus(&memstatus);
843   
844    sprintf (tmpstr, "TotalPhys: %i Meg\n", (int)(memstatus.dwTotalPhys/1024/1024));
845    log_message (tmpstr);
846    sprintf (tmpstr, "AvailPhys: %i Meg\n", (int)(memstatus.dwAvailPhys/1024/1024));
847    log_message (tmpstr);
848    sprintf (tmpstr, "TotalPageFile: %i Meg\n", (int)(memstatus.dwTotalPageFile/1024/1024));
849    log_message (tmpstr);
850    sprintf (tmpstr, "AvailPageFile: %i Meg\n", (int)(memstatus.dwAvailPageFile/1024/1024));
851    log_message (tmpstr);
852    sprintf (tmpstr, "TotalVirtual: %i Meg\n", (int)(memstatus.dwTotalVirtual/1024/1024));
853    log_message (tmpstr);
854    sprintf (tmpstr, "AvailVirtual: %i Meg\n\n", (int)(memstatus.dwAvailVirtual/1024/1024));
855    log_message (tmpstr);
856   
857    // log the version number
858    log_message("GSDL version: " GSDL_VERSION "\n");
859  }
860 
861}
862
863// possible command line options are
864// --location=directory (the path to GSDLHOME which defaults to the
865// directory where server.exe lives)
866// --config=file (the path to the configuration file to use which defaults
867// to GSDLHOME\llssite.cfg)
868// --cmd=init  Used to initialize the llssite.cfg file only - jmt12 18/11/2003
869static void parse_args(const text_t cmdline, text_t &location, text_t &config_file, text_t &command) {
870
871  location.clear();
872  config_file.clear();
873  command.clear(); // jmt12 18/11/2003
874
875  if (cmdline.size() < 3) return;
876
877  text_t name, val;
878  bool foundname = false;
879  text_t::const_iterator here = cmdline.begin();
880  text_t::const_iterator end = cmdline.end();
881  while (here != end) {
882    if (*here == '-' && ((here+1) != end) && (*(here+1) == '-')) {
883      ++here;
884      if (name == "location") {
885    location = val;
886      } else if (name == "config") {
887    config_file = val;
888      } else if(name == "cmd") { // jmt12 18/11/2003
889    command = val;
890      }
891      foundname = false;
892      name.clear();
893      val.clear();
894    } else if (*here == '=') {
895      foundname = true;
896    } else {
897      if (foundname) {
898    val.push_back(*here);
899      } else {
900    name.push_back(*here);
901      }
902    }
903    ++here;
904  }
905  if (name == "location") {
906    location = val;
907  } else if (name == "config") {
908    config_file = val;
909  } else if(name == "cmd") { // jmt12 18/11/2003
910    command = val;
911  }
912}
913
914
915// Tries to generate llssite.cfg from llssite.cfg.in in directory given
916// by location variable (assumes location is GSDLHOME), if llsite.cfg is missing
917void ensure_llssite_cfg(const text_t location) {
918  text_t configfile = location+"\llssite.cfg";
919  text_t configtemplate = location+"\llssite.cfg.in";
920
921  if(!file_exists (configfile)) {
922   
923    if(file_exists (configtemplate)) {
924      // try creating llssite.cfg from the template configfile llssite.cfg.in
925      // by using a straightforward copy
926      file_copy(configtemplate, configfile);
927    }
928  }
929}
930
931
932// Added code to allow for an 'init' run of the server which just creates the llssite.cfg file
933int __stdcall WinMain(HINSTANCE Instance, HINSTANCE /*PrevInstance*/, LPSTR CmdLineStr, int /*CmdShow*/) {
934  HWND MainWindow;  MSG Message;  WNDCLASS MainClass; 
935
936  // One instance of the local library server is quite enough, thank you very much
937  HWND gw = FindWindow("Greenstone Digital Library Software",
938               "Greenstone Digital Library Software");
939  if (gw != NULL) {
940    exit(1);
941  }
942
943  // parse arguments
944  text_t location, config_file, command;
945  parse_args(CmdLineStr, location, config_file, command);
946  gsdl_conffile = config_file;
947 
948  // Try to generate the llssite.cfg file if it's missing
949  ensure_llssite_cfg(location);
950
951  // jmt12 18/11/2003
952  if(command == "init") {
953    // init various modules
954    read_settings(0); // don't know if netscape is needed at this point
955    finish_up(true);
956    exit(0);
957  }
958
959  //Create a window class
960  MainClass.style = CS_HREDRAW | CS_VREDRAW;
961  MainClass.lpfnWndProc = WndProc;
962  MainClass.cbClsExtra = 0;
963  MainClass.cbWndExtra = 0;
964  MainClass.hInstance = Instance;
965  MainClass.hIcon     = LoadIcon(Instance, MAKEINTRESOURCE(TRAY_ICON));
966  MainClass.hCursor   = LoadCursor(NULL, IDC_ARROW);
967  MainClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
968  MainClass.lpszMenuName = MAKEINTRESOURCE(Main_Menu);
969  MainClass.lpszClassName = "Greenstone Digital Library Software";
970  if (!RegisterClass(&MainClass))
971    return 0;
972 
973 
974  // Load various bitmaps
975  coltitlebitmap = LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_COL_TITLE));
976  logobitmap= LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_LOGO));
977 
978  // Create the main window
979  MainWindow = CreateWindow("Greenstone Digital Library Software",
980                "Greenstone Digital Library Software",
981                WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
982                WS_MINIMIZEBOX,
983                CW_USEDEFAULT, CW_USEDEFAULT,
984                MAINWINDOWWIDTH + WASTEWIDTH,
985                MAINWINDOWHEIGHT + WASTEHEIGHT,
986                NULL, NULL, Instance, NULL);
987 
988  text_rect.left = 0; 
989  text_rect.top = VERSIONY+VERSIONHEIGHT + 5;
990  text_rect.right = MAINWINDOWWIDTH;
991  text_rect.bottom = LOGOY-SPACERWIDTH;
992 
993  window_state = undefined_window;
994 
995  ShowWindow(MainWindow, SW_SHOW);
996  set_location(location);
997 
998  // get ready to draw the main window
999  RECT windowRect;
1000  GetClientRect (MainWindow, &windowRect);
1001  HDC pdc = GetDC (MainWindow);
1002 
1003  // retrieve and save the text metrics
1004  TEXTMETRIC tm;
1005  GetTextMetrics(pdc, &tm);
1006  line_spacing = tm.tmHeight + tm.tmExternalLeading;
1007  GSDL_Window = MainWindow; 
1008
1009  // init various modules
1010  read_settings (0); // don't know if netscape is needed at this point
1011 
1012  if (!gsdl_auto_enter) {
1013   
1014    // add the select version checkbox
1015    Enter = CreateWindow("BUTTON",             // predefined class
1016             "Enter Library",      // button text
1017             WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_DEFPUSHBUTTON,  // styles
1018             ENTERBUTTONX,         // starting x position
1019             ENTERBUTTONY,         // starting y position
1020             ENTERBUTTONWIDTH,     // button width
1021             ENTERBUTTONHEIGHT,    // button height
1022             MainWindow,           // parent window
1023             NULL,                 // No menu
1024             Instance,
1025             NULL);                // pointer not needed
1026   
1027//      EnterRestricted = CreateWindow("Button",                // predefined class
1028//                     "Restricted Version",    // button text
1029//                     WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_PUSHBUTTON,   // styles
1030//                     ALTERNATIVEBUTTONX,      // starting x position
1031//                     ALTERNATIVEBUTTONY,      // starting y position
1032//                     ALTERNATIVEBUTTONWIDTH-(INFOBUTTONWIDTH+SPACERWIDTH),  // button width
1033//                     ALTERNATIVEBUTTONHEIGHT, // button height
1034//                     MainWindow,              // parent window
1035//                     (HMENU)NULL,             // No menu
1036//                     Instance,
1037//                     NULL);                   // pointer not needed
1038   
1039//      InfoRestricted = CreateWindow("Button",                // predefined class
1040//                    NULL,
1041//                    WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_BITMAP,   // styles
1042//                    ALTERNATIVEBUTTONWIDTH-INFOBUTTONWIDTH+SPACERWIDTH, // starting x position
1043//                    ALTERNATIVEBUTTONY,      // starting y position
1044//                    INFOBUTTONWIDTH,         // button width
1045//                    ALTERNATIVEBUTTONHEIGHT, // button height
1046//                    MainWindow,              // parent window
1047//                    (HMENU)NULL,             // No menu
1048//                    Instance,
1049//                    NULL);                   // pointer not needed
1050   
1051//      HANDLE i_icon = LoadImage (Instance, MAKEINTRESOURCE(GSDL_ICBMP), IMAGE_BITMAP,
1052//                     INFOBUTTONWIDTH-4, ALTERNATIVEBUTTONHEIGHT-4, LR_DEFAULTCOLOR);
1053//      SendMessage (InfoRestricted, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)i_icon);
1054   
1055    SetFocus (Enter);
1056   
1057    enterstring = strenterlib;
1058    paint_window (pdc, windowRect);
1059   
1060    // message loop for init buttons
1061    while (!init_done) {
1062      if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1063    if (Message.message == WM_QUIT) return Message.wParam;
1064    if (!IsDialogMessage (MainWindow, &Message)) {
1065      TranslateMessage(&Message); /* translate keyboard messages */
1066      DispatchMessage(&Message);  /* return control to Windows NT */
1067    }
1068      } else {
1069    Sleep (1);
1070      }
1071    }
1072   
1073    // don't want these buttons anymore
1074    DestroyWindow (Enter);
1075    // DestroyWindow (EnterRestricted);
1076    // DestroyWindow (InfoRestricted);
1077   
1078    enterstring = strnothing;
1079    paint_window (pdc, windowRect);
1080   
1081  } else {
1082    // auto enter is enabled - start up standard version
1083    init_type = 1;
1084    init_done = 1;
1085  }
1086 
1087  // draw the main window containing an init message
1088  infostring = strinit;
1089  paint_window (pdc, windowRect);
1090  DWORD lastcheck = GetTickCount();
1091 
1092  have_networking = initnetwork (Instance, MainWindow);
1093  if (!have_networking) {
1094    MessageBox(NULL,
1095           "Failed to initialize networking.",
1096           "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1097    exit (0);
1098  }
1099
1100  if (!gsdl_init()) // quit if can't initialise the library correctly
1101    exit (0);
1102  initstartbrowser();
1103  log_computer_info ();
1104 
1105  // show the initialising message for at least 1 second
1106  while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) {
1107    Sleep (1);
1108  }
1109 
1110  // attempt to start a browser
1111  if (gsdl_show_console || !gsdl_start_browser) infostring = strnothing;
1112  else infostring = strsb;
1113  paint_window (pdc, windowRect);
1114  lastcheck = GetTickCount();
1115  if (enter_library (MainWindow) && !gsdl_show_console) {
1116    // stay maximised for at least 1 second
1117    while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) Sleep (1);
1118    ShowWindow(MainWindow,SW_MINIMIZE);
1119  }
1120 
1121  // add the "restart library" button
1122  GoButton = CreateWindow("BUTTON",              // predefined class
1123              "Restart Library",     // button text
1124              WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // styles
1125              RESTARTBUTTONX,        // starting x position
1126              RESTARTBUTTONY,        // starting y position
1127              RESTARTBUTTONWIDTH,    // button width
1128              RESTARTBUTTONHEIGHT,   // button height
1129              MainWindow,            // parent window
1130              NULL,                  // No menu
1131              Instance,
1132              NULL);                 // pointer not needed
1133 
1134  infostring = strrestartlib;
1135  paint_window (pdc, windowRect);
1136 
1137  // release the DC used to display the init messages
1138  ReleaseDC (MainWindow, pdc);
1139 
1140  //Message loop
1141  lastcheck = GetTickCount();
1142  int seenbrowser = 0;  // if we see a browser then it disappears
1143                        // we will ask if they want to close the
1144                        // the library down
1145  char last_gsdl_browser_exe[MAX_FILENAME_SIZE]; // need to notice when the
1146                                                 // browser setting changes
1147  strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1148 
1149  for (;;) {
1150    if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1151      if (Message.message == WM_QUIT) break;
1152      if (!IsDialogMessage (MainWindow, &Message)) {
1153    TranslateMessage(&Message); /* translate keyboard messages */
1154    DispatchMessage(&Message);  /* return control to Windows NT */
1155      }
1156     
1157    } else {
1158      if (DiffTickCounts (lastcheck, GetTickCount()) > 500) {
1159    // make sure the browser hasn't changed
1160    if (strcmp (last_gsdl_browser_exe, gsdl_browser_exe) != 0) {
1161      seenbrowser = 0;
1162      strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1163    }
1164   
1165    // do check
1166    lastcheck = GetTickCount();
1167    if (gsdl_start_browser && browserrunning(gsdl_browser_exe) == NO_ERROR) {
1168      // we were able to connect to a browser
1169      seenbrowser = 1;
1170     
1171      // see if the enter library button has been pressed
1172      // with nothing happening for 20 seconds
1173      if ((enterlib_libaccessnum >= 0) &&
1174          (enterlib_libaccessnum == libaccessnum) &&
1175          (DiffTickCounts (enterlib_time, GetTickCount()) > 20000)) {
1176        // something could be wrong!! (most likely cause is a proxy)
1177        MessageBox(NULL,
1178               "Your browser does not seem to be responding to the 'Enter Library'\n"
1179               "request. Try turning off all proxy servers in your browser settings.\n"
1180               "If you are using Internet Explorer make sure BOTH dialup settings\n"
1181               "AND LAN settings have their proxy servers disabled.",
1182               "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1183        enterlib_libaccessnum = -1;
1184      }
1185     
1186     
1187    } else {
1188      // no browser was found
1189     
1190      if (seenbrowser) {
1191        // we have seen a browser in the past
1192        if (MessageBox(NULL,
1193               "The Greenstone Digital Library software has noticed that you\n"
1194               "shut down your browser. Would you also like to shut down the\n"
1195               "Greenstone Digital Library software?",
1196               "Greenstone Digital Library Software",MB_YESNO|MB_SYSTEMMODAL) == IDYES)
1197          PostMessage(MainWindow,WM_CLOSE,0,0);
1198      }
1199      seenbrowser = 0;
1200    }
1201      }
1202     
1203      Sleep (1); // millisecond
1204    }
1205  }
1206 
1207  return Message.wParam;
1208}
1209
Note: See TracBrowser for help on using the browser.