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

Last change on this file since 20949 was 20949, checked in by ak19, 14 years ago

Need to write out hostIP in case we were using this address-resolution-method, and then next time started up the apache server instead of server.exe.

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