source: branches/gsdl-2_70-distribution-branch/gsdl/src/w32server/fnord.cpp@ 11721

Last change on this file since 11721 was 11721, checked in by kjdon, 18 years ago

added Michael's changes to remove restricted version to the branch

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 37.0 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
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\gsdlsite.cfg)
867// --cmd=init Used to initialize the gsdlsite.cfg file onlt - 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 }
888 // jmt12 18/11/2003
889 else if(name == "cmd") {
890 command = val;
891 }
892 foundname = false;
893 name.clear();
894 val.clear();
895 } else if (*here == '=') {
896 foundname = true;
897 } else {
898 if (foundname) {
899 val.push_back(*here);
900 } else {
901 name.push_back(*here);
902 }
903 }
904 ++here;
905 }
906 if (name == "location") {
907 location = val;
908 } else if (name == "config") {
909 config_file = val;
910 }
911 // jmt12 18/11/2003
912 else if(name == "cmd") {
913 command = val;
914 }
915}
916
917// Added code to allow for an 'init' run of the server which just creates the gsdlsite.cfg file
918int __stdcall WinMain(HINSTANCE Instance, HINSTANCE /*PrevInstance*/, LPSTR CmdLineStr, int /*CmdShow*/) {
919 HWND MainWindow; MSG Message; WNDCLASS MainClass;
920
921 // One instance of the local library server is quite enough, thank you very much
922 HWND gw = FindWindow("Greenstone Digital Library Software",
923 "Greenstone Digital Library Software");
924 if (gw != NULL) {
925 exit(1);
926 }
927
928 // parse arguments
929 text_t location, config_file, command;
930 parse_args(CmdLineStr, location, config_file, command);
931 gsdl_conffile = config_file;
932
933 // jmt12 18/11/2003
934 if(command == "init") {
935 // init various modules
936 read_settings(0); // don't know if netscape is needed at this point
937 finish_up(true);
938 exit(0);
939 }
940
941 //Create a window class
942 MainClass.style = CS_HREDRAW | CS_VREDRAW;
943 MainClass.lpfnWndProc = WndProc;
944 MainClass.cbClsExtra = 0;
945 MainClass.cbWndExtra = 0;
946 MainClass.hInstance = Instance;
947 MainClass.hIcon = LoadIcon(Instance, MAKEINTRESOURCE(TRAY_ICON));
948 MainClass.hCursor = LoadCursor(NULL, IDC_ARROW);
949 MainClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
950 MainClass.lpszMenuName = MAKEINTRESOURCE(Main_Menu);
951 MainClass.lpszClassName = "Greenstone Digital Library Software";
952 if (!RegisterClass(&MainClass))
953 return 0;
954
955
956 // Load various bitmaps
957 coltitlebitmap = LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_COL_TITLE));
958 logobitmap= LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_LOGO));
959
960 // Create the main window
961 MainWindow = CreateWindow("Greenstone Digital Library Software",
962 "Greenstone Digital Library Software",
963 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
964 WS_MINIMIZEBOX,
965 CW_USEDEFAULT, CW_USEDEFAULT,
966 MAINWINDOWWIDTH + WASTEWIDTH,
967 MAINWINDOWHEIGHT + WASTEHEIGHT,
968 NULL, NULL, Instance, NULL);
969
970 text_rect.left = 0;
971 text_rect.top = VERSIONY+VERSIONHEIGHT + 5;
972 text_rect.right = MAINWINDOWWIDTH;
973 text_rect.bottom = LOGOY-SPACERWIDTH;
974
975 window_state = undefined_window;
976
977 ShowWindow(MainWindow, SW_SHOW);
978 set_location(location);
979
980 // get ready to draw the main window
981 RECT windowRect;
982 GetClientRect (MainWindow, &windowRect);
983 HDC pdc = GetDC (MainWindow);
984
985 // retrieve and save the text metrics
986 TEXTMETRIC tm;
987 GetTextMetrics(pdc, &tm);
988 line_spacing = tm.tmHeight + tm.tmExternalLeading;
989 GSDL_Window = MainWindow;
990
991 // init various modules
992 read_settings (0); // don't know if netscape is needed at this point
993
994 if (!gsdl_auto_enter) {
995
996 // add the select version checkbox
997 Enter = CreateWindow("BUTTON", // predefined class
998 "Enter Library", // button text
999 WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_DEFPUSHBUTTON, // styles
1000 ENTERBUTTONX, // starting x position
1001 ENTERBUTTONY, // starting y position
1002 ENTERBUTTONWIDTH, // button width
1003 ENTERBUTTONHEIGHT, // button height
1004 MainWindow, // parent window
1005 NULL, // No menu
1006 Instance,
1007 NULL); // pointer not needed
1008
1009// EnterRestricted = CreateWindow("Button", // predefined class
1010// "Restricted Version", // button text
1011// WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_PUSHBUTTON, // styles
1012// ALTERNATIVEBUTTONX, // starting x position
1013// ALTERNATIVEBUTTONY, // starting y position
1014// ALTERNATIVEBUTTONWIDTH-(INFOBUTTONWIDTH+SPACERWIDTH), // button width
1015// ALTERNATIVEBUTTONHEIGHT, // button height
1016// MainWindow, // parent window
1017// (HMENU)NULL, // No menu
1018// Instance,
1019// NULL); // pointer not needed
1020
1021// InfoRestricted = CreateWindow("Button", // predefined class
1022// NULL,
1023// WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_BITMAP, // styles
1024// ALTERNATIVEBUTTONWIDTH-INFOBUTTONWIDTH+SPACERWIDTH, // starting x position
1025// ALTERNATIVEBUTTONY, // starting y position
1026// INFOBUTTONWIDTH, // button width
1027// ALTERNATIVEBUTTONHEIGHT, // button height
1028// MainWindow, // parent window
1029// (HMENU)NULL, // No menu
1030// Instance,
1031// NULL); // pointer not needed
1032
1033// HANDLE i_icon = LoadImage (Instance, MAKEINTRESOURCE(GSDL_ICBMP), IMAGE_BITMAP,
1034// INFOBUTTONWIDTH-4, ALTERNATIVEBUTTONHEIGHT-4, LR_DEFAULTCOLOR);
1035// SendMessage (InfoRestricted, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)i_icon);
1036
1037 SetFocus (Enter);
1038
1039 enterstring = strenterlib;
1040 paint_window (pdc, windowRect);
1041
1042 // message loop for init buttons
1043 while (!init_done) {
1044 if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1045 if (Message.message == WM_QUIT) return Message.wParam;
1046 if (!IsDialogMessage (MainWindow, &Message)) {
1047 TranslateMessage(&Message); /* translate keyboard messages */
1048 DispatchMessage(&Message); /* return control to Windows NT */
1049 }
1050 } else {
1051 Sleep (1);
1052 }
1053 }
1054
1055 // don't want these buttons anymore
1056 DestroyWindow (Enter);
1057 // DestroyWindow (EnterRestricted);
1058 // DestroyWindow (InfoRestricted);
1059
1060 enterstring = strnothing;
1061 paint_window (pdc, windowRect);
1062
1063 } else {
1064 // auto enter is enabled - start up standard version
1065 init_type = 1;
1066 init_done = 1;
1067 }
1068
1069 // draw the main window containing an init message
1070 infostring = strinit;
1071 paint_window (pdc, windowRect);
1072 DWORD lastcheck = GetTickCount();
1073
1074 have_networking = initnetwork (Instance, MainWindow);
1075 if (!have_networking) {
1076 MessageBox(NULL,
1077 "Failed to initialize networking.",
1078 "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1079 exit (0);
1080 }
1081
1082 if (!gsdl_init()) // quit if can't initialise the library correctly
1083 exit (0);
1084 initstartbrowser();
1085 log_computer_info ();
1086
1087 // show the initialising message for at least 1 second
1088 while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) {
1089 Sleep (1);
1090 }
1091
1092 // attempt to start a browser
1093 if (gsdl_show_console || !gsdl_start_browser) infostring = strnothing;
1094 else infostring = strsb;
1095 paint_window (pdc, windowRect);
1096 lastcheck = GetTickCount();
1097 if (enter_library (MainWindow) && !gsdl_show_console) {
1098 // stay maximised for at least 1 second
1099 while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) Sleep (1);
1100 ShowWindow(MainWindow,SW_MINIMIZE);
1101 }
1102
1103 // add the "restart library" button
1104 GoButton = CreateWindow("BUTTON", // predefined class
1105 "Restart Library", // button text
1106 WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // styles
1107 RESTARTBUTTONX, // starting x position
1108 RESTARTBUTTONY, // starting y position
1109 RESTARTBUTTONWIDTH, // button width
1110 RESTARTBUTTONHEIGHT, // button height
1111 MainWindow, // parent window
1112 NULL, // No menu
1113 Instance,
1114 NULL); // pointer not needed
1115
1116 infostring = strrestartlib;
1117 paint_window (pdc, windowRect);
1118
1119 // release the DC used to display the init messages
1120 ReleaseDC (MainWindow, pdc);
1121
1122 //Message loop
1123 lastcheck = GetTickCount();
1124 int seenbrowser = 0; // if we see a browser then it disappears
1125 // we will ask if they want to close the
1126 // the library down
1127 char last_gsdl_browser_exe[MAX_FILENAME_SIZE]; // need to notice when the
1128 // browser setting changes
1129 strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1130
1131 for (;;) {
1132 if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1133 if (Message.message == WM_QUIT) break;
1134 if (!IsDialogMessage (MainWindow, &Message)) {
1135 TranslateMessage(&Message); /* translate keyboard messages */
1136 DispatchMessage(&Message); /* return control to Windows NT */
1137 }
1138
1139 } else {
1140 if (DiffTickCounts (lastcheck, GetTickCount()) > 500) {
1141 // make sure the browser hasn't changed
1142 if (strcmp (last_gsdl_browser_exe, gsdl_browser_exe) != 0) {
1143 seenbrowser = 0;
1144 strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1145 }
1146
1147 // do check
1148 lastcheck = GetTickCount();
1149 if (gsdl_start_browser && browserrunning(gsdl_browser_exe) == NO_ERROR) {
1150 // we were able to connect to a browser
1151 seenbrowser = 1;
1152
1153 // see if the enter library button has been pressed
1154 // with nothing happening for 20 seconds
1155 if ((enterlib_libaccessnum >= 0) &&
1156 (enterlib_libaccessnum == libaccessnum) &&
1157 (DiffTickCounts (enterlib_time, GetTickCount()) > 20000)) {
1158 // something could be wrong!! (most likely cause is a proxy)
1159 MessageBox(NULL,
1160 "Your browser does not seem to be responding to the 'Enter Library'\n"
1161 "request. Try turning off all proxy servers in your browser settings.\n"
1162 "If you are using Internet Explorer make sure BOTH dialup settings\n"
1163 "AND LAN settings have their proxy servers disabled.",
1164 "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1165 enterlib_libaccessnum = -1;
1166 }
1167
1168
1169 } else {
1170 // no browser was found
1171
1172 if (seenbrowser) {
1173 // we have seen a browser in the past
1174 if (MessageBox(NULL,
1175 "The Greenstone Digital Library software has noticed that you\n"
1176 "shut down your browser. Would you also like to shut down the\n"
1177 "Greenstone Digital Library software?",
1178 "Greenstone Digital Library Software",MB_YESNO|MB_SYSTEMMODAL) == IDYES)
1179 PostMessage(MainWindow,WM_CLOSE,0,0);
1180 }
1181 seenbrowser = 0;
1182 }
1183 }
1184
1185 Sleep (1); // millisecond
1186 }
1187 }
1188
1189 return Message.wParam;
1190}
1191
Note: See TracBrowser for help on using the repository browser.