source: main/tags/2.51-fiji/gsdl/src/w32server/fnord.cpp@ 26313

Last change on this file since 26313 was 7610, checked in by mdewsnip, 20 years ago

Added code to prevent the local library server being run multiple times at once.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 36.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;
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 char *localname = GetLocalName(NULL);
333 if (have_networking) {
334 text_t url = "http://" + text_t(localname);
335
336 gsdl_url = url;
337 write_settings(gsdl_url);
338
339 if (gsdl_port_num != 80)
340 url += ":" + text_t(gsdl_port_num);
341
342 url += gsdl_enterlib;
343
344 // add a unique ending so it will always result in a request
345 text_t::const_iterator it =
346 findchar (gsdl_enterlib.begin(), gsdl_enterlib.end(), '?');
347 if (it == gsdl_enterlib.end()) url.push_back ('?');
348 else url.push_back ('&');
349 int tcount = GetTickCount();
350 url += "uq=" + text_t(tcount);
351
352 // remember the library access number for later proxy checking
353 enterlib_libaccessnum = libaccessnum;
354
355 if (gsdl_start_browser) {
356
357 // do a quick check to make sure we're using netscape when
358 // we should be (it might have been just installed)
359 if (netscapeneeded) gsdl_check_browser_settings (netscapeneeded);
360
361 char *cstr_url = url.getcstr();
362 if (strlen (startbrowserdir) <= 0) {
363 res = startbrowser (cstr_url, gsdl_browser_exe, NULL);
364
365 } else res = startbrowser (cstr_url, gsdl_browser_exe, startbrowserdir);
366
367 delete cstr_url;
368
369 } else {
370 return 1;
371 }
372 }
373
374 if (res == SB_NOERROR) {
375 // success !!
376
377 // remember the time the browser was started for later proxy checking
378 if (have_networking) enterlib_time = GetTickCount();
379
380 return 1;
381 }
382
383 // no browser was started
384 enterlib_libaccessnum = -1;
385
386 if ((res == SB_FAIL_BADFORMAT) || (res == SB_FAIL_NOTFOUND)) {
387 if (!netscapeneeded) { // any browser
388 MessageBox(Window,
389 "Failed to start your chosen browser. It seems that your\n"
390 "chosen browser has been removed or corrupted.\n"
391 "Please check your browser choice by going to the\n"
392 "'Settings...' item under the 'File' menu.",
393 "Greenstone Digital Library Software", MB_OK);
394 } else { // netscape used
395 MessageBox(Window,
396 "Failed to start Netscape. It seems that Netscape has\n"
397 "been removed or corrupted. You need Netscape\n"
398 "installed to use the Greenstone Digital Library\n"
399 "software on non-networked machines.",
400 "Greenstone Digital Library Software", MB_OK);
401 }
402
403 } else {
404 MessageBox(Window,
405 "Failed to start your browser. This may have been\n"
406 "because there was not enough memory available. Shut\n"
407 "down all other applications you have running, and\n"
408 "try again.",
409 "Greenstone Digital Library Software", MB_OK);
410 }
411
412 return 0; // failed
413}
414
415
416void install_netscape (HWND Window) {
417 char installpath[256];
418
419 // try to find the browser directory
420 char *gsdlhome = gsdl_gsdlhome.getcstr();
421 strcpy (installpath, gsdlhome); // use gsdlhome to find the CD-ROM drive...
422 delete gsdlhome;
423
424 // remove any slashes from the pathname
425 int len = strlen (installpath);
426 while ((len > 0) && ((installpath[len-1] == '\\') || (installpath[len-1] == '/'))) {
427 len--;
428 }
429 // remove '\gsdl'
430 len = len - 5;
431 installpath[len] = '\0';
432
433 strcat (installpath, "\\netscape\\");
434
435 // check this directory
436 if (!cstrcheckdir(installpath)) {
437 return;
438 }
439
440 // get the operating system information
441 OSVERSIONINFO osver;
442 memset(&osver, 0, sizeof(OSVERSIONINFO));
443 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
444 GetVersionEx(&osver);
445
446 // get the install program for this operating system
447 if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
448 strcat (installpath, "n16e405.exe");
449 } else {
450 strcat (installpath, "n32e405.exe");
451 }
452
453 // run the install program
454 int res = WinExec (installpath, SW_SHOW);
455 if (res == 0) {
456 // out of resources or memory
457 MessageBox (Window,
458 "Did not have enough resources or memory to run the\n"
459 "install program. Try shutting down all other programs\n"
460 "and trying again.",
461 "Greenstone Digital Library Software",
462 MB_OK|MB_APPLMODAL);
463
464 } else if (res == ERROR_BAD_FORMAT) {
465 // executable image is corrupt -- ????
466 MessageBox (Window,
467 "The install program seems to be corrupt.",
468 "Greenstone Digital Library Software",
469 MB_OK|MB_APPLMODAL);
470
471 } else if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_PATH_NOT_FOUND)) {
472 // couldn't find the executable -- ????
473 MessageBox (Window,
474 "Could not find the install program. Try installing\n"
475 "Netscape from the Greenstone Digital Library\n"
476 "software's install program.",
477 "Greenstone Digital Library Software",
478 MB_OK|MB_APPLMODAL);
479 }
480}
481
482void open_help () {
483 char topdir[256], cmd[256];
484
485 // try to find the browser directory
486 char *gsdlhome = gsdl_gsdlhome.getcstr();
487 strcpy (topdir, gsdlhome); // use gsdlhome to find the CD-ROM drive...
488 delete gsdlhome;
489 strcpy (cmd, "notepad ");
490
491 // remove any slashes from the pathname
492 int len = strlen (topdir);
493 while ((len > 0) && ((topdir[len-1] == '\\') || (topdir[len-1] == '/'))) {
494 len--;
495 }
496 // remove the '\gsdl'
497 len = len - 5;
498 topdir[len] = '\0';
499
500 strcat (topdir, "\\README.txt");
501 strcat (cmd, topdir);
502
503 WinExec (cmd, SW_SHOW);
504}
505
506
507long __stdcall WndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam) {
508 switch(Message) {
509 // Constant Messages
510 case WM_CREATE:
511 break;
512
513 case WM_COMMAND:
514 if ((GoButton != NULL) && ((HWND)LParam == GoButton)) {
515 // attempt to start a browser
516 gsdl_start_browser = 1;
517 if (enter_library (Window) && !gsdl_show_console)
518 ShowWindow(Window,SW_MINIMIZE);
519
520 } else if ((Enter != NULL) && ((HWND)LParam == Enter)) {
521 init_done = 1;
522 init_type = 1;
523
524 } else if ((EnterRestricted != NULL) && ((HWND)LParam == EnterRestricted)) {
525 init_done = 1;
526 init_type = 0;
527
528 } else if ((InfoRestricted != NULL) && ((HWND)LParam == InfoRestricted)) {
529 MessageBox (NULL, "The Greenstone system automatically determines whether your computer has\n"
530 "network software installed or is connected to a network. It operates correctly\n"
531 "under any of these conditions.\n\n"
532 "The restricted version is intended for use when the standard one\n\n"
533 " (a) causes an unwanted telephone dialup operation;\n"
534 " (b) fails to run because network software is installed, but installed\n"
535 " incorrectly.\n\n"
536 "The restricted version only works with Netscape (not Internet Explorer).\n\n"
537 "Unless these problems arise, you should always use the standard version\n"
538 "(press the 'Enter Library' button).\n",
539 "Greenstone Digital Library Software",
540 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
541
542 } else {
543 switch (LOWORD(WParam)) {
544 case ID_PROJECT_SETTINGS:
545 Settings_Dialog(Window, netscapeneeded);
546 break;
547 case ID_INSTALL_NETSCAPE:
548 install_netscape(Window);
549 break;
550 case IDHELP:
551 open_help();
552 break;
553 case ID_PROJECT_EXIT:
554 finish_up(false);
555 break;
556 default:
557 break;
558 }
559 }
560 break;
561
562 case WM_PAINT:
563 handle_painting(Window);
564 break;
565
566 case HTTP_SERVER_MSG:
567 ProcessHTTPServerMsg(WParam, LParam);
568 break;
569
570 case WM_DESTROY:
571 finish_up(false);
572 break;
573
574 default:
575 //Unhandled Messages end up here (DefWindowProc)
576 return DefWindowProc(Window, Message, WParam, LParam);
577 }
578
579 return(0);
580}
581
582// returns 0 if successful,
583// otherwise a WSA error number
584int tryinitnetwork (HANDLE Instance, HWND MsgWindow, char *path) {
585 // try to load winsock
586 int err = d_LoadWinsock (path);
587
588 if (err == D_NOERROR) {
589 // next, try to init netio
590 err = InitNetIO();
591
592 if (err == 0) {
593 // next, try to start the http server
594 err = StartHTTPServer(MsgWindow);
595
596 if (err == 0) {
597 // finally, get the host name (no error value
598 // is returned from this function)
599 GetLocalName((HINSTANCE)Instance);
600
601 } else {
602 // couldn't start the http server,
603 // deinit netio and unload winsock
604 CleanUpNetIO();
605 d_UnloadWinsock();
606 }
607
608 } else {
609 // couldn't init netio, unload winsock
610 d_UnloadWinsock();
611 }
612
613 } else {
614 // couldn't load winsock
615 err = WSASYSNOTREADY;
616 }
617
618 return err;
619}
620
621
622// inits all the network functionality
623// returns 0 if an unrecoverable error occurred,
624// and 1 if everything successfully initialised.
625int initnetwork (HANDLE Instance, HWND MsgWindow) {
626 OSVERSIONINFO osver;
627
628 // get the operating system information
629 memset(&osver, 0, sizeof(OSVERSIONINFO));
630 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
631 GetVersionEx(&osver);
632
633 // first try to initialise the network with system installed
634 // networking software
635 startbrowserdir[0] = '\0';
636 netscapeneeded = 0;
637 int err = 1;
638 if (init_type == 1) err = tryinitnetwork (Instance, MsgWindow, NULL);
639
640 // if an error occurred, try again with billsock
641 if (err != 0) {
642 // get the path of billsock (current directory + ("net16" | "net32"))
643 char winsockpath[1024]; // HARD LIMIT!!!!
644
645 find_location();
646 char *data_location_c = data_location.getcstr();
647 strcpy (winsockpath, data_location_c);
648 delete data_location_c;
649
650 // remove all the slashes at the end of billpath
651 int len = strlen (winsockpath);
652 while ((len > 0) && ((winsockpath[len-1] == '\\') || (winsockpath[len-1] == '/'))) {
653 len--;
654 }
655 winsockpath[len] = '\0';
656
657 if (osver.dwPlatformId == VER_PLATFORM_WIN32s)
658 strcat (winsockpath, "\\net16\\");
659 else {
660 strcat (winsockpath, "\\net32\\");
661 strcpy (startbrowserdir, winsockpath);
662 }
663
664 // try again
665 err = tryinitnetwork (Instance, MsgWindow, winsockpath);
666
667 if (err == 0) {
668 // we will need to use netscape on 95/98/NT machines
669 if (osver.dwPlatformId != VER_PLATFORM_WIN32s) {
670 netscapeneeded = 1;
671 // make sure the browser state is in step with the network condition
672 gsdl_check_browser_settings (netscapeneeded);
673 }
674
675 // check to see if a browser is running
676 if (browserrunning(gsdl_browser_exe) == NO_ERROR) {
677 MessageBox (NULL,
678 "The Greenstone Digital Library software has detected a\n"
679 "running browser. To let our networking software\n"
680 "correctly initialize, please shut down your browser\n"
681 "and restart the Greenstone Digital Library software.",
682 "Greenstone Digital Library Software", MB_OK|MB_APPLMODAL);
683 PostMessage(MsgWindow,WM_CLOSE,0,0);
684 finish_up(false); // will unload winsock
685 exit(0); // nothing more to do
686 }
687 }
688 }
689
690 // if an error occurred display a nice error message
691 if (err != 0) {
692
693 // WSASYSNOTREADY Couldn't load winsock
694 // WSAVERNOTSUPPORTED The version of Windows Sockets support requested
695 // is not provided by this particular Windows Sockets implementation.
696 // WSAEINVAL The Windows Sockets version specified by the application
697 // is not supported by this DLL.
698 // WSAEPROTONOSUPPORT The specified protocol is not supported.
699 // WSAEPROTOTYPE The specified protocol is the wrong type for this socket.
700 // WSAESOCKTNOSUPPORT The specified socket type is not supported in
701 // this address family.
702 // WSANOTINITIALISED A successful WSAStartup must occur before
703 // using this function.
704 // WSAENETDOWN The Windows Sockets implementation
705 // has detected that the network subsystem has failed.
706 // WSAEADDRINUSE The specified address
707 // is already in use. (See the SO_REUSEADDR socket option under setsockopt.)
708 // WSAEFAULT The namelen argument is too small (less
709 // than the size of a struct sockaddr).
710 // WSAEINPROGRESS A blocking Windows Sockets call is in progress.
711 // WSAEAFNOSUPPORT The specified address family is not supported
712 // by this protocol.
713 // WSAENOBUFS Not enough buffers available, too many connections.
714 // WSAENOTSOCK The descriptor is not a socket.
715 // WSAEISCONN The socket is already connected.
716 // WSAEMFILE No more file descriptors are available.
717 // WSAEOPNOTSUPP The referenced socket is not of a type that
718 // supports the listen operation.
719
720 // get a text version of the error number
721 char errstr[256];
722
723 switch (err) {
724 case WSASYSNOTREADY: strcpy(errstr, "WSASYSNOTREADY");
725 break;
726 case WSAVERNOTSUPPORTED: strcpy (errstr, "WSAVERNOTSUPPORTED");
727 break;
728 case WSAEINVAL: strcpy (errstr, "WSAEINVAL");
729 break;
730 case WSAEPROTONOSUPPORT: strcpy (errstr, "WSAEPROTONOSUPPORT");
731 break;
732 case WSAEPROTOTYPE: strcpy (errstr, "WSAEPROTOTYPE");
733 break;
734 case WSAESOCKTNOSUPPORT: strcpy (errstr, "WSAESOCKTNOSUPPORT");
735 break;
736 case WSANOTINITIALISED: strcpy (errstr, "WSANOTINITIALISED");
737 break;
738 case WSAEFAULT: strcpy (errstr, "WSAEFAULT");
739 break;
740 case WSAEAFNOSUPPORT: strcpy (errstr, "WSAEAFNOSUPPORT");
741 break;
742 case WSAENOTSOCK: strcpy (errstr, "WSAENOTSOCK");
743 break;
744 case WSAEISCONN: strcpy (errstr, "WSAEISCONN");
745 break;
746 case WSAEOPNOTSUPP: strcpy (errstr, "WSAEOPNOTSUPP");
747 break;
748 case WSAENETDOWN: strcpy (errstr, "WSAENETDOWN");
749 break;
750 case WSAEADDRINUSE: strcpy (errstr, "WSAEADDRINUSE");
751 break;
752 case WSAEINPROGRESS: strcpy (errstr, "WSAEINPROGRESS");
753 break;
754 case WSAENOBUFS: strcpy (errstr, "WSAENOBUFS");
755 break;
756 case WSAEMFILE: strcpy (errstr, "WSAEMFILE");
757 break;
758 default: sprintf (errstr, "WSA ERROR: %i", err);
759 break;
760 }
761
762 // create a nice error message
763 char message[2048];
764
765 switch (err) {
766 case WSAEADDRINUSE:
767 // couldn't bind socket
768 sprintf (message, "Could not find a free socket.", errstr);
769 break;
770
771 default:
772 // cannot init winsock
773 sprintf (message, "Could not initialize the network\n"
774 " (Reason: %s).", errstr);
775 break;
776 }
777
778 strcat (message, "\n\n"
779 "Please submit a bug report using the support.htm file\n"
780 "on the CD-ROM.");
781
782 MessageBox (NULL, message, "Greenstone Digital Library Software", MB_OK);
783 }
784
785 return (err == 0);
786}
787
788
789void log_computer_info () {
790 char tmpstr[1024];
791
792 // get various information about this computer
793 if (gsdl_keep_log || gsdl_show_console) {
794 // get operating system information
795 OSVERSIONINFO osver;
796 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
797
798 if (GetVersionEx(&osver)) {
799 if (osver.dwPlatformId == VER_PLATFORM_WIN32s) {
800 log_message ("Platform: win32s\n");
801 } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
802 log_message ("Platform: windows 95\n");
803 } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
804 log_message ("Platform: windows NT\n");
805 }
806
807 sprintf (tmpstr, "MajorVersion: %i\n", (int)osver.dwMajorVersion);
808 log_message(tmpstr);
809 sprintf (tmpstr, "MinorVersion: %i\n", (int)osver.dwMinorVersion);
810 log_message(tmpstr);
811 sprintf (tmpstr, "BuildNumber: %i\n", (int)osver.dwBuildNumber);
812 log_message(tmpstr);
813 sprintf (tmpstr, "CSDVersion: %s\n\n", osver.szCSDVersion);
814 log_message(tmpstr);
815 }
816
817 // get memory information
818 MEMORYSTATUS memstatus;
819 memstatus.dwLength = sizeof(MEMORYSTATUS);
820 GlobalMemoryStatus(&memstatus);
821
822 sprintf (tmpstr, "TotalPhys: %i Meg\n", (int)(memstatus.dwTotalPhys/1024/1024));
823 log_message (tmpstr);
824 sprintf (tmpstr, "AvailPhys: %i Meg\n", (int)(memstatus.dwAvailPhys/1024/1024));
825 log_message (tmpstr);
826 sprintf (tmpstr, "TotalPageFile: %i Meg\n", (int)(memstatus.dwTotalPageFile/1024/1024));
827 log_message (tmpstr);
828 sprintf (tmpstr, "AvailPageFile: %i Meg\n", (int)(memstatus.dwAvailPageFile/1024/1024));
829 log_message (tmpstr);
830 sprintf (tmpstr, "TotalVirtual: %i Meg\n", (int)(memstatus.dwTotalVirtual/1024/1024));
831 log_message (tmpstr);
832 sprintf (tmpstr, "AvailVirtual: %i Meg\n\n", (int)(memstatus.dwAvailVirtual/1024/1024));
833 log_message (tmpstr);
834
835 // log the version number
836 log_message("GSDL version: " GSDL_VERSION "\n");
837 }
838
839}
840
841// possible command line options are
842// --location=directory (the path to GSDLHOME which defaults to the
843// directory where server.exe lives)
844// --config=file (the path to the configuration file to use which defaults
845// to GSDLHOME\gsdlsite.cfg)
846// --cmd=init Used to initialize the gsdlsite.cfg file onlt - jmt12 18/11/2003
847static void parse_args(const text_t cmdline, text_t &location, text_t &config_file, text_t &command) {
848
849 location.clear();
850 config_file.clear();
851 command.clear(); // jmt12 18/11/2003
852
853 if (cmdline.size() < 3) return;
854
855 text_t name, val;
856 bool foundname = false;
857 text_t::const_iterator here = cmdline.begin();
858 text_t::const_iterator end = cmdline.end();
859 while (here != end) {
860 if (*here == '-' && ((here+1) != end) && (*(here+1) == '-')) {
861 here++;
862 if (name == "location") {
863 location = val;
864 } else if (name == "config") {
865 config_file = val;
866 }
867 // jmt12 18/11/2003
868 else if(name == "cmd") {
869 command = val;
870 }
871 foundname = false;
872 name.clear();
873 val.clear();
874 } else if (*here == '=') {
875 foundname = true;
876 } else {
877 if (foundname) {
878 val.push_back(*here);
879 } else {
880 name.push_back(*here);
881 }
882 }
883 here++;
884 }
885 if (name == "location") {
886 location = val;
887 } else if (name == "config") {
888 config_file = val;
889 }
890 // jmt12 18/11/2003
891 else if(name == "cmd") {
892 command = val;
893 }
894}
895
896// Added code to allow for an 'init' run of the server which just creates the gsdlsite.cfg file
897int __stdcall WinMain(HINSTANCE Instance, HINSTANCE /*PrevInstance*/, LPSTR CmdLineStr, int /*CmdShow*/) {
898 HWND MainWindow; MSG Message; WNDCLASS MainClass;
899
900 // One instance of the local library server is quite enough, thank you very much
901 HWND gw = FindWindow("Greenstone Digital Library Software",
902 "Greenstone Digital Library Software");
903 if (gw != NULL) {
904 exit(1);
905 }
906
907 // parse arguments
908 text_t location, config_file, command;
909 parse_args(CmdLineStr, location, config_file, command);
910 gsdl_conffile = config_file;
911
912 // jmt12 18/11/2003
913 if(command == "init") {
914 // init various modules
915 read_settings(0); // don't know if netscape is needed at this point
916 finish_up(true);
917 exit(0);
918 }
919
920 //Create a window class
921 MainClass.style = CS_HREDRAW | CS_VREDRAW;
922 MainClass.lpfnWndProc = WndProc;
923 MainClass.cbClsExtra = 0;
924 MainClass.cbWndExtra = 0;
925 MainClass.hInstance = Instance;
926 MainClass.hIcon = LoadIcon(Instance, MAKEINTRESOURCE(TRAY_ICON));
927 MainClass.hCursor = LoadCursor(NULL, IDC_ARROW);
928 MainClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
929 MainClass.lpszMenuName = MAKEINTRESOURCE(Main_Menu);
930 MainClass.lpszClassName = "Greenstone Digital Library Software";
931 if (!RegisterClass(&MainClass))
932 return 0;
933
934
935 // Load various bitmaps
936 coltitlebitmap = LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_COL_TITLE));
937 logobitmap= LoadBitmap (Instance, MAKEINTRESOURCE(GSDL_LOGO));
938
939 // Create the main window
940 MainWindow = CreateWindow("Greenstone Digital Library Software",
941 "Greenstone Digital Library Software",
942 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
943 WS_MINIMIZEBOX,
944 CW_USEDEFAULT, CW_USEDEFAULT,
945 MAINWINDOWWIDTH + WASTEWIDTH,
946 MAINWINDOWHEIGHT + WASTEHEIGHT,
947 NULL, NULL, Instance, NULL);
948
949 text_rect.left = 0;
950 text_rect.top = VERSIONY+VERSIONHEIGHT + 5;
951 text_rect.right = MAINWINDOWWIDTH;
952 text_rect.bottom = LOGOY-SPACERWIDTH;
953
954 window_state = undefined_window;
955
956 ShowWindow(MainWindow, SW_SHOW);
957 set_location(location);
958
959 // get ready to draw the main window
960 RECT windowRect;
961 GetClientRect (MainWindow, &windowRect);
962 HDC pdc = GetDC (MainWindow);
963
964 // retrieve and save the text metrics
965 TEXTMETRIC tm;
966 GetTextMetrics(pdc, &tm);
967 line_spacing = tm.tmHeight + tm.tmExternalLeading;
968 GSDL_Window = MainWindow;
969
970 // init various modules
971 read_settings (0); // don't know if netscape is needed at this point
972
973 if (!gsdl_auto_enter) {
974
975 // add the select version checkbox
976 Enter = CreateWindow("BUTTON", // predefined class
977 "Enter Library", // button text
978 WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_DEFPUSHBUTTON, // styles
979 ENTERBUTTONX, // starting x position
980 ENTERBUTTONY, // starting y position
981 ENTERBUTTONWIDTH, // button width
982 ENTERBUTTONHEIGHT, // button height
983 MainWindow, // parent window
984 NULL, // No menu
985 Instance,
986 NULL); // pointer not needed
987
988 EnterRestricted = CreateWindow("Button", // predefined class
989 "Restricted Version", // button text
990 WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_PUSHBUTTON, // styles
991 ALTERNATIVEBUTTONX, // starting x position
992 ALTERNATIVEBUTTONY, // starting y position
993 ALTERNATIVEBUTTONWIDTH-(INFOBUTTONWIDTH+SPACERWIDTH), // button width
994 ALTERNATIVEBUTTONHEIGHT, // button height
995 MainWindow, // parent window
996 (HMENU)NULL, // No menu
997 Instance,
998 NULL); // pointer not needed
999
1000 InfoRestricted = CreateWindow("Button", // predefined class
1001 NULL,
1002 WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_BITMAP, // styles
1003 ALTERNATIVEBUTTONWIDTH-INFOBUTTONWIDTH+SPACERWIDTH, // starting x position
1004 ALTERNATIVEBUTTONY, // starting y position
1005 INFOBUTTONWIDTH, // button width
1006 ALTERNATIVEBUTTONHEIGHT, // button height
1007 MainWindow, // parent window
1008 (HMENU)NULL, // No menu
1009 Instance,
1010 NULL); // pointer not needed
1011
1012 HANDLE i_icon = LoadImage (Instance, MAKEINTRESOURCE(GSDL_ICBMP), IMAGE_BITMAP,
1013 INFOBUTTONWIDTH-4, ALTERNATIVEBUTTONHEIGHT-4, LR_DEFAULTCOLOR);
1014 SendMessage (InfoRestricted, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)i_icon);
1015
1016 SetFocus (Enter);
1017
1018 enterstring = strenterlib;
1019 paint_window (pdc, windowRect);
1020
1021 // message loop for init buttons
1022 while (!init_done) {
1023 if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1024 if (Message.message == WM_QUIT) return Message.wParam;
1025 if (!IsDialogMessage (MainWindow, &Message)) {
1026 TranslateMessage(&Message); /* translate keyboard messages */
1027 DispatchMessage(&Message); /* return control to Windows NT */
1028 }
1029 } else {
1030 Sleep (1);
1031 }
1032 }
1033
1034 // don't want these buttons anymore
1035 DestroyWindow (Enter);
1036 DestroyWindow (EnterRestricted);
1037 DestroyWindow (InfoRestricted);
1038
1039 enterstring = strnothing;
1040 paint_window (pdc, windowRect);
1041
1042 } else {
1043 // auto enter is enabled - start up standard version
1044 init_type = 1;
1045 init_done = 1;
1046 }
1047
1048 // draw the main window containing an init message
1049 infostring = strinit;
1050 paint_window (pdc, windowRect);
1051 DWORD lastcheck = GetTickCount();
1052
1053 have_networking = initnetwork (Instance, MainWindow);
1054 if (!have_networking) {
1055 MessageBox(NULL,
1056 "Failed to initialize networking.",
1057 "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1058 exit (0);
1059 }
1060
1061 if (!gsdl_init()) // quit if can't initialise the library correctly
1062 exit (0);
1063 initstartbrowser();
1064 log_computer_info ();
1065
1066 // show the initialising message for at least 1 second
1067 while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) {
1068 Sleep (1);
1069 }
1070
1071 // attempt to start a browser
1072 if (gsdl_show_console || !gsdl_start_browser) infostring = strnothing;
1073 else infostring = strsb;
1074 paint_window (pdc, windowRect);
1075 lastcheck = GetTickCount();
1076 if (enter_library (MainWindow) && !gsdl_show_console) {
1077 // stay maximised for at least 1 second
1078 while (DiffTickCounts (lastcheck, GetTickCount()) < 1000) Sleep (1);
1079 ShowWindow(MainWindow,SW_MINIMIZE);
1080 }
1081
1082 // add the "restart library" button
1083 GoButton = CreateWindow("BUTTON", // predefined class
1084 "Restart Library", // button text
1085 WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // styles
1086 RESTARTBUTTONX, // starting x position
1087 RESTARTBUTTONY, // starting y position
1088 RESTARTBUTTONWIDTH, // button width
1089 RESTARTBUTTONHEIGHT, // button height
1090 MainWindow, // parent window
1091 NULL, // No menu
1092 Instance,
1093 NULL); // pointer not needed
1094
1095 infostring = strrestartlib;
1096 paint_window (pdc, windowRect);
1097
1098 // release the DC used to display the init messages
1099 ReleaseDC (MainWindow, pdc);
1100
1101 //Message loop
1102 lastcheck = GetTickCount();
1103 int seenbrowser = 0; // if we see a browser then it disappears
1104 // we will ask if they want to close the
1105 // the library down
1106 char last_gsdl_browser_exe[MAX_FILENAME_SIZE]; // need to notice when the
1107 // browser setting changes
1108 strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1109
1110 for (;;) {
1111 if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) {
1112 if (Message.message == WM_QUIT) break;
1113 if (!IsDialogMessage (MainWindow, &Message)) {
1114 TranslateMessage(&Message); /* translate keyboard messages */
1115 DispatchMessage(&Message); /* return control to Windows NT */
1116 }
1117
1118 } else {
1119 if (DiffTickCounts (lastcheck, GetTickCount()) > 500) {
1120 // make sure the browser hasn't changed
1121 if (strcmp (last_gsdl_browser_exe, gsdl_browser_exe) != 0) {
1122 seenbrowser = 0;
1123 strcpy (last_gsdl_browser_exe, gsdl_browser_exe);
1124 }
1125
1126 // do check
1127 lastcheck = GetTickCount();
1128 if (gsdl_start_browser && browserrunning(gsdl_browser_exe) == NO_ERROR) {
1129 // we were able to connect to a browser
1130 seenbrowser = 1;
1131
1132 // see if the enter library button has been pressed
1133 // with nothing happening for 20 seconds
1134 if ((enterlib_libaccessnum >= 0) &&
1135 (enterlib_libaccessnum == libaccessnum) &&
1136 (DiffTickCounts (enterlib_time, GetTickCount()) > 20000)) {
1137 // something could be wrong!! (most likely cause is a proxy)
1138 MessageBox(NULL,
1139 "Your browser does not seem to be responding to the 'Enter Library'\n"
1140 "request. Try turning off all proxy servers in your browser settings.\n"
1141 "If you are using Internet Explorer make sure BOTH dialup settings\n"
1142 "AND LAN settings have their proxy servers disabled.",
1143 "Greenstone Digital Library Software",MB_OK|MB_SYSTEMMODAL);
1144 enterlib_libaccessnum = -1;
1145 }
1146
1147
1148 } else {
1149 // no browser was found
1150
1151 if (seenbrowser) {
1152 // we have seen a browser in the past
1153 if (MessageBox(NULL,
1154 "The Greenstone Digital Library software has noticed that you\n"
1155 "shut down your browser. Would you also like to shut down the\n"
1156 "Greenstone Digital Library software?",
1157 "Greenstone Digital Library Software",MB_YESNO|MB_SYSTEMMODAL) == IDYES)
1158 PostMessage(MainWindow,WM_CLOSE,0,0);
1159 }
1160 seenbrowser = 0;
1161 }
1162 }
1163
1164 Sleep (1); // millisecond
1165 }
1166 }
1167
1168 return Message.wParam;
1169}
1170
Note: See TracBrowser for help on using the repository browser.