source: gsdl/trunk/runtime-src/src/w32server/fnord.cpp@ 18838

Last change on this file since 18838 was 18838, checked in by ak19, 15 years ago

Added a line in that seemed like an ommission: command.clear().

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