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

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

Recommitting the changes made to allow GLI to work with the independently-launched GSI.

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