source: trunk/gsdl/src/w32server/fnord.cpp@ 10648

Last change on this file since 10648 was 10231, checked in by mdewsnip, 19 years ago

Added some alternative methods of resolving the address the local library will attempt to load, since many people have reported problems with the existing method lately. The first new method determines the IP but doesn't resolve it to a name, and the second new method always uses "127.0.0.1". This option is controlled using the "address_resolution_method" option in the Local Library gsdlsite.cfg file.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 36.7 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;
137HWND EnterRestricted = NULL;
138HWND 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 three 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: 127.0.0.1 -- always use 127.0.0.1
337 char gsdl_address[100];
338
339 DWORD local_ip = GetLocalIP();
340 if (local_ip == INADDR_ANY || gsdl_address_resolution_method == 2) {
341 local_ip = 127 + (0 << 8) + (0 << 16) + (1 << 24);
342 }
343
344 if (gsdl_address_resolution_method == 1 || gsdl_address_resolution_method == 2) {
345 sprintf(gsdl_address, "%d.%d.%d.%d", local_ip & 0xFF, (local_ip >> 8) & 0xFF, (local_ip >> 16) & 0xFF, (local_ip >> 24) & 0xFF);
346 }
347 else {
348 strcpy(gsdl_address, GetLocalName(NULL));
349 }
350
351 text_t url = "http://" + text_t(gsdl_address);
352
353 gsdl_url = url;
354 write_settings(gsdl_url);
355
356 if (gsdl_port_num != 80)
357 url += ":" + text_t(gsdl_port_num);
358
359 url += gsdl_enterlib;
360
361 // add a unique ending so it will always result in a request
362 text_t::const_iterator it =
363 findchar (gsdl_enterlib.begin(), gsdl_enterlib.end(), '?');
364 if (it == gsdl_enterlib.end()) url.push_back ('?');
365 else url.push_back ('&');
366 int tcount = GetTickCount();
367 url += "uq=" + text_t(tcount);
368
369 // remember the library access number for later proxy checking
370 enterlib_libaccessnum = libaccessnum;
371
372 if (gsdl_start_browser) {
373
374 // do a quick check to make sure we're using netscape when
375 // we should be (it might have been just installed)
376 if (netscapeneeded) gsdl_check_browser_settings (netscapeneeded);
377
378 char *cstr_url = url.getcstr();
379 if (strlen (startbrowserdir) <= 0) {
380 res = startbrowser (cstr_url, gsdl_browser_exe, NULL);
381
382 } else res = startbrowser (cstr_url, gsdl_browser_exe, startbrowserdir);
383
384 delete []cstr_url;
385
386 } else {
387 return 1;
388 }
389 }
390
391 if (res == SB_NOERROR) {
392 // success !!
393
394 // remember the time the browser was started for later proxy checking
395 if (have_networking) enterlib_time = GetTickCount();
396
397 return 1;
398 }
399
400 // no browser was started
401 enterlib_libaccessnum = -1;
402
403 if ((res == SB_FAIL_BADFORMAT) || (res == SB_FAIL_NOTFOUND)) {
404 if (!netscapeneeded) { // any browser
405 MessageBox(Window,
406 "Failed to start your chosen browser. It seems that your\n"
407 "chosen browser has been removed or corrupted.\n"
408 "Please check your browser choice by going to the\n"
409 "'Settings...' item under the 'File' menu.",
410 "Greenstone Digital Library Software", MB_OK);
411 } else { // netscape used
412 MessageBox(Window,
413 "Failed to start Netscape. It seems that Netscape has\n"
414 "been removed or corrupted. You need Netscape\n"
415 "installed to use the Greenstone Digital Library\n"
416 "software on non-networked machines.",
417 "Greenstone Digital Library Software", MB_OK);
418 }
419
420 } else {
421 MessageBox(Window,
422 "Failed to start your browser. This may have been\n"
423 "because there was not enough memory available. Shut\n"
424 "down all other applications you have running, and\n"
425 "try again.",
426 "Greenstone Digital Library Software", MB_OK);
427 }
428
429 return 0; // failed
430}
431
432
433void install_netscape (HWND Window) {
434 char installpath[256];
435
436 // try to find the browser directory
437 char *gsdlhome = gsdl_gsdlhome.getcstr();
438 strcpy (installpath, gsdlhome); // use gsdlhome to find the CD-ROM drive...
439 delete []gsdlhome;
440
441 // remove any slashes from the pathname
442 int len = strlen (installpath);
443 while ((len > 0) && ((installpath[len-1] == '\\') || (installpath[len-1] == '/'))) {
444 --len;
445 }
446 // remove '\gsdl'
447 len = len - 5;
448 installpath[len] = '\0';
449
450 strcat (installpath, "\\netscape\\");
451
452 // check this directory
453 if (!cstrcheckdir(installpath)) {
454 return;
455 }
456
457 // get the operating system information
458 OSVERSIONINFO osver;
459 memset(&osver, 0, sizeof(OSVERSIONINFO));
460 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
461 GetVersionEx(&osver);
462
463 // get the install program for this operating system
464 if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
465 strcat (installpath, "n16e405.exe");
466 } else {
467 strcat (installpath, "n32e405.exe");
468 }
469
470 // run the install program
471 int res = WinExec (installpath, SW_SHOW);
472 if (res == 0) {
473 // out of resources or memory
474 MessageBox (Window,
475 "Did not have enough resources or memory to run the\n"
476 "install program. Try shutting down all other programs\n"
477 "and trying again.",
478 "Greenstone Digital Library Software",
479 MB_OK|MB_APPLMODAL);
480
481 } else if (res == ERROR_BAD_FORMAT) {
482 // executable image is corrupt -- ????
483 MessageBox (Window,
484 "The install program seems to be corrupt.",
485 "Greenstone Digital Library Software",
486 MB_OK|MB_APPLMODAL);
487
488 } else if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_PATH_NOT_FOUND)) {
489 // couldn't find the executable -- ????
490 MessageBox (Window,
491 "Could not find the install program. Try installing\n"
492 "Netscape from the Greenstone Digital Library\n"
493 "software's install program.",
494 "Greenstone Digital Library Software",
495 MB_OK|MB_APPLMODAL);
496 }
497}
498
499void open_help () {
500 char topdir[256], cmd[256];
501
502 // try to find the browser directory
503 char *gsdlhome = gsdl_gsdlhome.getcstr();
504 strcpy (topdir, gsdlhome); // use gsdlhome to find the CD-ROM drive...
505 delete []gsdlhome;
506 strcpy (cmd, "notepad ");
507
508 // remove any slashes from the pathname
509 int len = strlen (topdir);
510 while ((len > 0) && ((topdir[len-1] == '\\') || (topdir[len-1] == '/'))) {
511 --len;
512 }
513 // remove the '\gsdl'
514 len = len - 5;
515 topdir[len] = '\0';
516
517 strcat (topdir, "\\README.txt");
518 strcat (cmd, topdir);
519
520 WinExec (cmd, SW_SHOW);
521}
522
523
524long __stdcall WndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam) {
525 switch(Message) {
526 // Constant Messages
527 case WM_CREATE:
528 break;
529
530 case WM_COMMAND:
531 if ((GoButton != NULL) && ((HWND)LParam == GoButton)) {
532 // attempt to start a browser
533 gsdl_start_browser = 1;
534 if (enter_library (Window) && !gsdl_show_console)
535 ShowWindow(Window,SW_MINIMIZE);
536
537 } else if ((Enter != NULL) && ((HWND)LParam == Enter)) {
538 init_done = 1;
539 init_type = 1;
540
541 } else if ((EnterRestricted != NULL) && ((HWND)LParam == EnterRestricted)) {
542 init_done = 1;
543 init_type = 0;
544
545 } else if ((InfoRestricted != NULL) && ((HWND)LParam == InfoRestricted)) {
546 MessageBox (NULL, "The Greenstone system automatically determines whether your computer has\n"
547 "network software installed or is connected to a network. It operates correctly\n"
548 "under any of these conditions.\n\n"
549 "The restricted version is intended for use when the standard one\n\n"
550 " (a) causes an unwanted telephone dialup operation;\n"
551 " (b) fails to run because network software is installed, but installed\n"
552 " incorrectly.\n\n"
553 "The restricted version only works with Netscape (not Internet Explorer).\n\n"
554 "Unless these problems arise, you should always use the standard version\n"
555 "(press the 'Enter Library' button).\n",
556 "Greenstone Digital Library Software",
557 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
558
559 } else {
560 switch (LOWORD(WParam)) {
561 case ID_PROJECT_SETTINGS:
562 Settings_Dialog(Window, netscapeneeded);
563 break;
564 case ID_INSTALL_NETSCAPE:
565 install_netscape(Window);
566 break;
567 case IDHELP:
568 open_help();
569 break;
570 case ID_PROJECT_EXIT:
571 finish_up(false);
572 break;
573 default:
574 break;
575 }
576 }
577 break;
578
579 case WM_PAINT:
580 handle_painting(Window);
581 break;
582
583 case HTTP_SERVER_MSG:
584 ProcessHTTPServerMsg(WParam, LParam);
585 break;
586
587 case WM_DESTROY:
588 finish_up(false);
589 break;
590
591 default:
592 //Unhandled Messages end up here (DefWindowProc)
593 return DefWindowProc(Window, Message, WParam, LParam);
594 }
595
596 return(0);
597}
598
599// returns 0 if successful,
600// otherwise a WSA error number
601int tryinitnetwork (HANDLE Instance, HWND MsgWindow, char *path) {
602 // try to load winsock
603 int err = d_LoadWinsock (path);
604
605 if (err == D_NOERROR) {
606 // next, try to init netio
607 err = InitNetIO();
608
609 if (err == 0) {
610 // next, try to start the http server
611 err = StartHTTPServer(MsgWindow);
612
613 if (err == 0) {
614 // finally, get the host name (no error value
615 // is returned from this function)
616 GetLocalName((HINSTANCE)Instance);
617
618 } else {
619 // couldn't start the http server,
620 // deinit netio and unload winsock
621 CleanUpNetIO();
622 d_UnloadWinsock();
623 }
624
625 } else {
626 // couldn't init netio, unload winsock
627 d_UnloadWinsock();
628 }
629
630 } else {
631 // couldn't load winsock
632 err = WSASYSNOTREADY;
633 }
634
635 return err;
636}
637
638
639// inits all the network functionality
640// returns 0 if an unrecoverable error occurred,
641// and 1 if everything successfully initialised.
642int initnetwork (HANDLE Instance, HWND MsgWindow) {
643 OSVERSIONINFO osver;
644
645 // get the operating system information
646 memset(&osver, 0, sizeof(OSVERSIONINFO));
647 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
648 GetVersionEx(&osver);
649
650 // first try to initialise the network with system installed
651 // networking software
652 startbrowserdir[0] = '\0';
653 netscapeneeded = 0;
654 int err = 1;
655 if (init_type == 1) err = tryinitnetwork (Instance, MsgWindow, NULL);
656
657 // if an error occurred, try again with billsock
658 if (err != 0) {
659 // get the path of billsock (current directory + ("net16" | "net32"))
660 char winsockpath[1024]; // HARD LIMIT!!!!
661
662 find_location();
663 char *data_location_c = data_location.getcstr();
664 strcpy (winsockpath, data_location_c);
665 delete []data_location_c;
666
667 // remove all the slashes at the end of billpath
668 int len = strlen (winsockpath);
669 while ((len > 0) && ((winsockpath[len-1] == '\\') || (winsockpath[len-1] == '/'))) {
670 --len;
671 }
672 winsockpath[len] = '\0';
673
674 if (osver.dwPlatformId == VER_PLATFORM_WIN32s)
675 strcat (winsockpath, "\\net16\\");
676 else {
677 strcat (winsockpath, "\\net32\\");
678 strcpy (startbrowserdir, winsockpath);
679 }
680
681 // try again
682 err = tryinitnetwork (Instance, MsgWindow, winsockpath);
683
684 if (err == 0) {
685 // we will need to use netscape on 95/98/NT machines
686 if (osver.dwPlatformId != VER_PLATFORM_WIN32s) {
687 netscapeneeded = 1;
688 // make sure the browser state is in step with the network condition
689 gsdl_check_browser_settings (netscapeneeded);
690 }
691
692 // check to see if a browser is running
693 if (browserrunning(gsdl_browser_exe) == NO_ERROR) {
694 MessageBox (NULL,
695 "The Greenstone Digital Library software has detected a\n"
696 "running browser. To let our networking software\n"
697 "correctly initialize, please shut down your browser\n"
698 "and restart the Greenstone Digital Library software.",
699 "Greenstone Digital Library Software", MB_OK|MB_APPLMODAL);
700 PostMessage(MsgWindow,WM_CLOSE,0,0);
701 finish_up(false); // will unload winsock
702 exit(0); // nothing more to do
703 }
704 }
705 }
706
707 // if an error occurred display a nice error message
708 if (err != 0) {
709
710 // WSASYSNOTREADY Couldn't load winsock
711 // WSAVERNOTSUPPORTED The version of Windows Sockets support requested
712 // is not provided by this particular Windows Sockets implementation.
713 // WSAEINVAL The Windows Sockets version specified by the application
714 // is not supported by this DLL.
715 // WSAEPROTONOSUPPORT The specified protocol is not supported.
716 // WSAEPROTOTYPE The specified protocol is the wrong type for this socket.
717 // WSAESOCKTNOSUPPORT The specified socket type is not supported in
718 // this address family.
719 // WSANOTINITIALISED A successful WSAStartup must occur before
720 // using this function.
721 // WSAENETDOWN The Windows Sockets implementation
722 // has detected that the network subsystem has failed.
723 // WSAEADDRINUSE The specified address
724 // is already in use. (See the SO_REUSEADDR socket option under setsockopt.)
725 // WSAEFAULT The namelen argument is too small (less
726 // than the size of a struct sockaddr).
727 // WSAEINPROGRESS A blocking Windows Sockets call is in progress.
728 // WSAEAFNOSUPPORT The specified address family is not supported
729 // by this protocol.
730 // WSAENOBUFS Not enough buffers available, too many connections.
731 // WSAENOTSOCK The descriptor is not a socket.
732 // WSAEISCONN The socket is already connected.
733 // WSAEMFILE No more file descriptors are available.
734 // WSAEOPNOTSUPP The referenced socket is not of a type that
735 // supports the listen operation.
736
737 // get a text version of the error number
738 char errstr[256];
739
740 switch (err) {
741 case WSASYSNOTREADY: strcpy(errstr, "WSASYSNOTREADY");
742 break;
743 case WSAVERNOTSUPPORTED: strcpy (errstr, "WSAVERNOTSUPPORTED");
744 break;
745 case WSAEINVAL: strcpy (errstr, "WSAEINVAL");
746 break;
747 case WSAEPROTONOSUPPORT: strcpy (errstr, "WSAEPROTONOSUPPORT");
748 break;
749 case WSAEPROTOTYPE: strcpy (errstr, "WSAEPROTOTYPE");
750 break;
751 case WSAESOCKTNOSUPPORT: strcpy (errstr, "WSAESOCKTNOSUPPORT");
752 break;
753 case WSANOTINITIALISED: strcpy (errstr, "WSANOTINITIALISED");
754 break;
755 case WSAEFAULT: strcpy (errstr, "WSAEFAULT");
756 break;
757 case WSAEAFNOSUPPORT: strcpy (errstr, "WSAEAFNOSUPPORT");
758 break;
759 case WSAENOTSOCK: strcpy (errstr, "WSAENOTSOCK");
760 break;
761 case WSAEISCONN: strcpy (errstr, "WSAEISCONN");
762 break;
763 case WSAEOPNOTSUPP: strcpy (errstr, "WSAEOPNOTSUPP");
764 break;
765 case WSAENETDOWN: strcpy (errstr, "WSAENETDOWN");
766 break;
767 case WSAEADDRINUSE: strcpy (errstr, "WSAEADDRINUSE");
768 break;
769 case WSAEINPROGRESS: strcpy (errstr, "WSAEINPROGRESS");
770 break;
771 case WSAENOBUFS: strcpy (errstr, "WSAENOBUFS");
772 break;
773 case WSAEMFILE: strcpy (errstr, "WSAEMFILE");
774 break;
775 default: sprintf (errstr, "WSA ERROR: %i", err);
776 break;
777 }
778
779 // create a nice error message
780 char message[2048];
781
782 switch (err) {
783 case WSAEADDRINUSE:
784 // couldn't bind socket
785 sprintf (message, "Could not find a free socket.", errstr);
786 break;
787
788 default:
789 // cannot init winsock
790 sprintf (message, "Could not initialize the network\n"
791 " (Reason: %s).", errstr);
792 break;
793 }
794
795 strcat (message, "\n\n"
796 "Please submit a bug report using the support.htm file\n"
797 "on the CD-ROM.");
798
799 MessageBox (NULL, message, "Greenstone Digital Library Software", MB_OK);
800 }
801
802 return (err == 0);
803}
804
805
806void log_computer_info () {
807 char tmpstr[1024];
808
809 // get various information about this computer
810 if (gsdl_keep_log || gsdl_show_console) {
811 // get operating system information
812 OSVERSIONINFO osver;
813 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
814
815 if (GetVersionEx(&osver)) {
816 if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
817 log_message ("Platform: win32s\n");
818 } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
819 log_message ("Platform: windows 95\n");
820 } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
821 log_message ("Platform: windows NT\n");
822 }
823
824 sprintf (tmpstr, "MajorVersion: %i\n", (int)osver.dwMajorVersion);
825 log_message(tmpstr);
826 sprintf (tmpstr, "MinorVersion: %i\n", (int)osver.dwMinorVersion);
827 log_message(tmpstr);
828 sprintf (tmpstr, "BuildNumber: %i\n", (int)osver.dwBuildNumber);
829 log_message(tmpstr);
830 sprintf (tmpstr, "CSDVersion: %s\n\n", osver.szCSDVersion);
831 log_message(tmpstr);
832 }
833
834 // get memory information
835 MEMORYSTATUS memstatus;
836 memstatus.dwLength = sizeof(MEMORYSTATUS);
837 GlobalMemoryStatus(&memstatus);
838
839 sprintf (tmpstr, "TotalPhys: %i Meg\n", (int)(memstatus.dwTotalPhys/1024/1024));
840 log_message (tmpstr);
841 sprintf (tmpstr, "AvailPhys: %i Meg\n", (int)(memstatus.dwAvailPhys/1024/1024));
842 log_message (tmpstr);
843 sprintf (tmpstr, "TotalPageFile: %i Meg\n", (int)(memstatus.dwTotalPageFile/1024/1024));
844 log_message (tmpstr);
845 sprintf (tmpstr, "AvailPageFile: %i Meg\n", (int)(memstatus.dwAvailPageFile/1024/1024));
846 log_message (tmpstr);
847 sprintf (tmpstr, "TotalVirtual: %i Meg\n", (int)(memstatus.dwTotalVirtual/1024/1024));
848 log_message (tmpstr);
849 sprintf (tmpstr, "AvailVirtual: %i Meg\n\n", (int)(memstatus.dwAvailVirtual/1024/1024));
850 log_message (tmpstr);
851
852 // log the version number
853 log_message("GSDL version: " GSDL_VERSION "\n");
854 }
855
856}
857
858// possible command line options are
859// --location=directory (the path to GSDLHOME which defaults to the
860// directory where server.exe lives)
861// --config=file (the path to the configuration file to use which defaults
862// to GSDLHOME\gsdlsite.cfg)
863// --cmd=init Used to initialize the gsdlsite.cfg file onlt - jmt12 18/11/2003
864static void parse_args(const text_t cmdline, text_t &location, text_t &config_file, text_t &command) {
865
866 location.clear();
867 config_file.clear();
868 command.clear(); // jmt12 18/11/2003
869
870 if (cmdline.size() < 3) return;
871
872 text_t name, val;
873 bool foundname = false;
874 text_t::const_iterator here = cmdline.begin();
875 text_t::const_iterator end = cmdline.end();
876 while (here != end) {
877 if (*here == '-' && ((here+1) != end) && (*(here+1) == '-')) {
878 ++here;
879 if (name == "location") {
880 location = val;
881 } else if (name == "config") {
882 config_file = val;
883 }
884 // jmt12 18/11/2003
885 else if(name == "cmd") {
886 command = val;
887 }
888 foundname = false;
889 name.clear();
890 val.clear();
891 } else if (*here == '=') {
892 foundname = true;
893 } else {
894 if (foundname) {
895 val.push_back(*here);
896 } else {
897 name.push_back(*here);
898 }
899 }
900 ++here;
901 }
902 if (name == "location") {
903 location = val;
904 } else if (name == "config") {
905 config_file = val;
906 }
907 // jmt12 18/11/2003
908 else if(name == "cmd") {
909 command = val;
910 }
911}
912
913// Added code to allow for an 'init' run of the server which just creates the gsdlsite.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 repository browser.