source: main/trunk/greenstone2/runtime-src/src/w32server/fnord.cpp@ 24504

Last change on this file since 24504 was 24504, checked in by ak19, 13 years ago

Still part of the changes for introducing the --mode=gli flag that's passed to the GS2 server so that we can merge the two cfg files glisite and llssite. 1. Bugfix: need to trim the mode parameter read in the from the file, because some whitespace was left at the end of it. 2. Now the url property in the config file is also to be prefixed with the mode, so that GLI's LocalLibraryServer can work out whether GLI launched the GSI or whether it was launched independently (outside GLI).

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