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

Revision 18841, 36.9 KB (checked in by ak19, 11 years ago)

Reverting previous erroneous commit

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