1 /*
2  * browser.c - win32 interface to web browser
3  *
4  * Copyright (C) 2000 Stephen F. White
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file "COPYING" for details); if
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  */
21 
22 #include <swt.h>
23 #include <windows.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include "WriteFlags.h"
27 #include "../../config.h"
28 #include "../../mysnprintf.h"
29 
30 #define DEFAULT_BROWSER "\"C:\\Program Files\\Internet Explorer\\IExplore.exe\""
31 #define DEFAULT_FIREFOX "\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\""
32 #define DEFAULT_EDGE    "\"C:\\Program Files\\C:\Windows\System32\cmd.exe start edge:\""
33 
34 #define STARTUP_TIMEOUT 10000
35 
36 typedef struct SBrowser {
37     STABLE  prefs;
38     char   *command;
39     char   *application;
40     int     vrmlLevel;
41     int     useRemote;
42     int     xtypExecute;
43     char   *remoteCommand;
44     char   *topic;
45 
46     DWORD   DDEInst;
47     HSZ     ourService;
48     HSZ     theirService;
49     HSZ     topicSZ;
50     HSZ     exitSZ;
51     HANDLE  hProcess;
52 } SBrowser;
53 
54 static int browserLaunch(char* command , HANDLE* hProcess,
55                          const char *path, SWND wnd);
56 static int browserConnect(SBROWSER browser);
57 static int browserGoTo(SBROWSER browser, const char *path);
58 static int bringToFront(SBROWSER browser);
59 static char *fmtMsg(LPCTSTR lpszFormat, ...);
60 static int getShellOpenCommand(SBROWSER browser, const char *extension);
61 static void saveBrowserPreferences(SBROWSER browser);
62 
63 /*******************/
64 /* browser preview */
65 /*******************/
66 
67 SBROWSER
swBrowserInit(STABLE prefs)68 swBrowserInit(STABLE prefs)
69 {
70     SBrowser *browser = malloc(sizeof(SBrowser));
71     browser->prefs = prefs;
72     browser->command = mystrdup(swGetPreference(prefs, "PreviewCommand", ""));
73     browser->useRemote = swGetIntPreference(prefs, "PreviewUseRemote", FALSE);
74     browser->vrmlLevel = swGetIntPreference(prefs, "PreviewVrmlLevel", X3DOM);
75     browser->xtypExecute = swGetIntPreference(prefs, "XtypExecuteDDE", FALSE);
76     browser->remoteCommand = mystrdup(swGetPreference(prefs,
77                                       "PreviewRemoteCommand", ""));
78     browser->application = mystrdup(swGetPreference(prefs,
79                                                     "PreviewApplication", ""));
80     browser->topic = mystrdup(swGetPreference(prefs, "PreviewTopic", ""));
81 
82     if (!browser->command[0])
83          getShellOpenCommand(browser, ".wrl");
84     if (!browser->command[0])
85          browser->command = strdup(DEFAULT_BROWSER);
86     if (!browser->remoteCommand[0])
87         browser->useRemote = FALSE;
88 
89     browser->hProcess = NULL;
90     browser->DDEInst = 0L;
91 
92     return browser;
93 }
94 
95 int
swBrowserGetVrmlLevel(SBROWSER browser)96 swBrowserGetVrmlLevel(SBROWSER browser)
97 {
98     return browser->vrmlLevel;
99 }
100 
101 int
swBrowserGetRemote(SBROWSER browser)102 swBrowserGetRemote(SBROWSER browser)
103 {
104     return browser->useRemote;
105 }
106 
107 void
swBrowserSetRemote(SBROWSER browser,int remote)108 swBrowserSetRemote(SBROWSER browser, int remote)
109 {
110     browser->useRemote = remote;
111 }
112 
113 void
swBrowserGetSettings(SBROWSER browser,const char ** command,int * vrmlLevel,int * useRemote,int * xtypExecute,const char ** remoteCommand,const char ** application,const char ** topic)114 swBrowserGetSettings(SBROWSER browser, const char **command,
115                      int* vrmlLevel, int *useRemote, int *xtypExecute,
116                      const char **remoteCommand, const char **application,
117                      const char **topic)
118 {
119     *command = browser->command;
120     *vrmlLevel = browser->vrmlLevel;
121     *xtypExecute = browser->xtypExecute;
122     *useRemote = browser->useRemote;
123     *remoteCommand = browser->remoteCommand;
124     *application = browser->application;
125     *topic = browser->topic;
126 }
127 
128 void
swBrowserSetSettings(SBROWSER browser,const char * command,int vrmlLevel,int useRemote,int xtypExecute,const char * remoteCommand,const char * application,const char * topic)129 swBrowserSetSettings(SBROWSER browser, const char *command,
130                      int vrmlLevel, int useRemote, int xtypExecute,
131                      const char *remoteCommand, const char *application,
132                      const char *topic)
133 {
134     char *oldCommand = strdup(command);
135     char *oldRemoteCommand = strdup(remoteCommand);
136     free(browser->command);
137     free(browser->remoteCommand);
138     free(browser->application);
139     free(browser->topic);
140 
141     browser->command = oldCommand;
142     browser->vrmlLevel = vrmlLevel;
143     browser->useRemote = useRemote;
144     browser->xtypExecute = xtypExecute;
145     browser->remoteCommand = oldRemoteCommand;
146     browser->application = mystrdup(application);
147     browser->topic = mystrdup(topic);
148 
149     saveBrowserPreferences(browser);
150 }
151 
152 static void
saveBrowserPreferences(SBROWSER browser)153 saveBrowserPreferences(SBROWSER browser)
154 {
155     swSetPreference(browser->prefs, "PreviewCommand", browser->command);
156     swSetIntPreference(browser->prefs, "PreviewVrmlLevel", browser->vrmlLevel);
157     swSetIntPreference(browser->prefs, "PreviewUseRemote", browser->useRemote);
158     swSetIntPreference(browser->prefs, "XtypExecuteDDE", browser->xtypExecute);
159     swSetPreference(browser->prefs, "PreviewRemoteCommand", browser->remoteCommand);
160     swSetPreference(browser->prefs, "PreviewApplication", browser->application);
161     swSetPreference(browser->prefs, "PreviewTopic", browser->topic);
162 }
163 
164 void
swBrowserSetDefault(SBROWSER browser)165 swBrowserSetDefault(SBROWSER browser)
166 {
167     browser->command = mystrdup("");
168     browser->useRemote = TRUE;
169     browser->vrmlLevel = X3DOM;
170     browser->xtypExecute = FALSE;
171     browser->remoteCommand = mystrdup("");
172     browser->application = mystrdup("");
173     browser->topic = mystrdup("");
174 
175     if (!browser->command[0])
176         getShellOpenCommand(browser, ".wrl");
177     if (!browser->command[0])
178         browser->command = strdup(DEFAULT_BROWSER);
179     if (!browser->remoteCommand[0])
180         browser->useRemote = FALSE;
181     browser->hProcess = NULL;
182     browser->DDEInst = 0L;
183 }
184 
185 void
swBrowserPreview(SBROWSER browser,const char * path,SWND wnd)186 swBrowserPreview(SBROWSER browser, const char *path, SWND wnd)
187 {
188     if (browser->useRemote != 0) {
189         if (browserLaunch(browser->remoteCommand,browser->hProcess, path, wnd))
190             browserGoTo(browser, path);
191     } else {
192         browserLaunch(browser->command,browser->hProcess, path, wnd);
193     }
194 }
195 
196 void
swBrowserShutdown(SBROWSER browser)197 swBrowserShutdown(SBROWSER browser)
198 {
199     saveBrowserPreferences(browser);
200     if (browser->hProcess) {
201         TerminateProcess(browser->hProcess, 1);
202         CloseHandle(browser->hProcess);
203     }
204     free(browser->command);
205     free(browser->remoteCommand);
206     free(browser->application);
207     free(browser->topic);
208 
209     if (browser->DDEInst != 0) {
210         DdeNameService( browser->DDEInst, NULL, NULL, DNS_UNREGISTER);
211         DdeFreeStringHandle( browser->DDEInst, browser->theirService);
212         DdeFreeStringHandle( browser->DDEInst, browser->ourService);
213         DdeFreeStringHandle( browser->DDEInst, browser->topicSZ);
214         DdeUninitialize( browser->DDEInst );
215     }
216     free(browser);
217 }
218 
219 static char *
fmtMsg(LPCTSTR lpszFormat,...)220 fmtMsg(LPCTSTR lpszFormat, ...)
221 {
222     char    *buf;
223     LPTSTR lpszTemp;
224 
225     // format message into temporary buffer lpszTemp
226     va_list argList;
227     va_start(argList, lpszFormat);
228 
229     FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
230                   lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList);
231 
232     // assign lpszTemp into the resulting string and free the temporary
233     buf = mystrdup(lpszTemp);
234     LocalFree(lpszTemp);
235     va_end(argList);
236     return buf;
237 }
238 
browserLaunch(char * command,HANDLE * hProcess,const char * path,SWND wnd)239 static int browserLaunch(char* command, HANDLE* hProcess, const char *path,
240                          SWND wnd)
241 {
242     STARTUPINFO startInfo;
243     PROCESS_INFORMATION processInfo;
244     int rc;
245     char *s, *cmdline;
246 
247     if (path && path[0]) {
248         if (strstr(command,"%s") == NULL)
249             cmdline = fmtMsg(command, path);
250         else {
251             // expand %s to path
252             char buf[1024];
253             mysnprintf(buf, 1023, command, path);
254             cmdline = mystrdup(buf);
255         }
256     } else {
257         cmdline = mystrdup(command);
258         if (cmdline[0] == '"') {
259             s = strchr(cmdline+1, '"');
260             if (s) (*(s+1)) = 0;
261         } else {
262             s = strchr(cmdline, ' ');
263             if (s) *s = 0;
264         }
265     }
266 
267     memset(&startInfo, 0, sizeof(startInfo));
268 
269     startInfo.cb = sizeof(STARTUPINFO);
270     startInfo.dwFlags = STARTF_USESHOWWINDOW;
271     startInfo.wShowWindow = SW_SHOWNA;
272 
273     if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
274                       &startInfo, &processInfo) != 0) {
275         WaitForInputIdle( processInfo.hProcess, STARTUP_TIMEOUT );
276         CloseHandle(processInfo.hThread);
277         hProcess = processInfo.hProcess;
278         rc = TRUE;
279     } else {
280         rc = FALSE;
281     }
282     free(cmdline);
283     return rc;
284 }
285 
DDECallback(UINT type,UINT fmt,HCONV hconv,HSZ hsz1,HSZ hsz2,HDDEDATA hData,DWORD dwData1,DWORD dwData2)286 static HDDEDATA DDECallback(
287     UINT type,          /* transaction type */
288     UINT fmt,           /* clipboard data format    */
289     HCONV hconv,        /* handle of conversation   */
290     HSZ hsz1,           /* handle of string */
291     HSZ hsz2,           /* handle of string */
292     HDDEDATA hData,     /* handle of global memory object   */
293     DWORD dwData1,      /* transaction-specific data    */
294     DWORD dwData2       /* transaction-specific data    */ )
295 {
296     return (HDDEDATA) 1;
297 }
298 
browserGoTo(SBROWSER browser,const char * path)299 static int browserGoTo(SBROWSER browser, const char *path)
300 {
301     char *buf;
302 
303     HSZ data;
304     HCONV conv;
305     HDDEDATA res;
306     int timeout = 120;
307     int rc = FALSE;
308 
309     if (browser->DDEInst == 0) {
310         if (!browserConnect(browser)) return FALSE;
311     }
312     conv = DdeConnect( browser->DDEInst, browser->theirService,
313                browser->topicSZ, NULL );
314     if (conv != NULL) {
315         buf = fmtMsg( browser->remoteCommand, path );
316         data = DdeCreateStringHandle( browser->DDEInst, buf, CP_WINANSI );
317 
318         if (browser->xtypExecute)
319             res = DdeClientTransaction(buf, strlen(buf)+1, conv, 0L, 0,
320                                         XTYP_EXECUTE, TIMEOUT_ASYNC, NULL);
321         else
322             res = DdeClientTransaction(NULL, 0, conv, data, CF_TEXT,
323                                        XTYP_REQUEST, TIMEOUT_ASYNC, NULL);
324 
325          DdeDisconnect( conv);
326          DdeFreeStringHandle( browser->DDEInst, data);
327          free(buf);
328          if (!browser->xtypExecute)
329              bringToFront(browser);
330          rc = TRUE;
331     }
332     return rc;
333 }
334 
queryValue(HKEY key,const char * subKey,char ** result)335 LONG queryValue(HKEY key, const char *subKey, char **result)
336 {
337     LONG size, rc;
338 
339     rc = RegQueryValue(key, subKey, NULL, &size);
340     if (rc == ERROR_SUCCESS) {
341         *result = (char *) malloc(size + 1);
342         RegQueryValue(key, subKey, *result, &size);
343     } else {
344         *result = mystrdup("");
345     }
346     return rc;
347 }
348 
349 static int
getShellOpenCommand(SBROWSER browser,const char * extension)350 getShellOpenCommand(SBROWSER browser, const char *extension)
351 {
352     HKEY key;
353     char *info;
354 
355     if (queryValue(HKEY_CLASSES_ROOT, extension, &info) != ERROR_SUCCESS) {
356         return FALSE;
357     }
358 
359     if (RegOpenKey(HKEY_CLASSES_ROOT, info, &key) != ERROR_SUCCESS) {
360         free(info);
361         return FALSE;
362     }
363 
364     free(browser->command);
365     free(browser->remoteCommand);
366     free(browser->application);
367     free(browser->topic);
368     queryValue(key, "Shell\\Open\\command", &browser->command);
369     queryValue(key, "Shell\\Open\\ddeexec", &browser->remoteCommand);
370     browser->useRemote = browser->remoteCommand[0];
371     queryValue(key, "Shell\\Open\\ddeexec\\Application", &browser->application);
372     queryValue(key, "Shell\\Open\\ddeexec\\Topic", &browser->topic);
373 
374     RegCloseKey(key);
375     free(info);
376     return TRUE;
377 }
378 
379 static int
browserConnect(SBROWSER browser)380 browserConnect(SBROWSER browser)
381 {
382     int rc = FALSE;
383 
384     UINT initRes = DdeInitialize(&browser->DDEInst,
385                                  (PFNCALLBACK) DDECallback,
386                                  APPCLASS_STANDARD |
387                                  CBF_FAIL_CONNECTIONS |
388                                  CBF_SKIP_DISCONNECTS,
389                                  0);
390 
391     if (initRes == DMLERR_NO_ERROR) {
392         browser->theirService = DdeCreateStringHandle(browser->DDEInst, browser->application, CP_WINANSI );
393         browser->ourService = DdeCreateStringHandle(browser->DDEInst, "Dune", CP_WINANSI );
394         browser->topicSZ = DdeCreateStringHandle(browser->DDEInst, browser->topic, CP_WINANSI );
395 
396         DdeNameService(browser->DDEInst, browser->ourService, NULL, DNS_REGISTER);
397         rc = TRUE;
398     }
399     return rc;
400 }
401 
bringToFront(SBROWSER browser)402 static int bringToFront(SBROWSER browser)
403 {
404     HSZ data, activate;
405     HCONV conv;
406     int timeout = 120;
407     int rc = FALSE;
408 
409     activate = DdeCreateStringHandle(browser->DDEInst, "WWW_Activate", CP_WINANSI );
410     conv = DdeConnect(browser->DDEInst, browser->theirService, activate, NULL );
411     if (conv != NULL) {
412         data = DdeCreateStringHandle(browser->DDEInst, "0xFFFFFFFF", CP_WINANSI );
413 
414         DdeClientTransaction(NULL, 0, conv, data, CF_TEXT, XTYP_REQUEST,
415                              TIMEOUT_ASYNC, NULL);
416 
417         DdeFreeStringHandle( browser->DDEInst, data);
418         DdeDisconnect( conv);
419         rc = TRUE;
420     }
421     DdeFreeStringHandle( browser->DDEInst, activate);
422     return rc;
423 }
424 
swRemoveFile(const char * filename)425 void swRemoveFile(const char* filename)
426 {
427     unlink(filename);
428 }
429 
430 
431 /**********/
432 /* upload */
433 /**********/
434 
435 typedef struct SUpload {
436     STABLE prefs;
437     char  *commandline;
438     char  *htmlTag;
439     char  *password;
440 } SUpload;
441 
442 SUPLOAD
swUploadInit(STABLE prefs)443 swUploadInit(STABLE prefs)
444 {
445     SUpload *upload = malloc(sizeof(SUpload));
446     upload->prefs = prefs;
447     upload->commandline = mystrdup(swGetPreference(prefs, "UploadCommandLine",
448                                                    ""));
449     upload->htmlTag = mystrdup(swGetPreference(prefs, "UploadHtmlTags",
450                                                ""));
451     /* do not read/store password for security reasons */
452     upload->password = malloc(1024);
453     upload->password[0] = 0;
454     VirtualLock(upload->password, 1024);
455 
456     return upload;
457 }
458 
459 void
swUploadGetSettings(SUPLOAD upload,const char ** commandline,const char ** htmlTag,const char ** password)460 swUploadGetSettings(SUPLOAD upload,
461                     const char **commandline,
462                     const char **htmlTag,
463                     const char **password)
464 {
465     *commandline = upload->commandline;
466     *htmlTag = upload->htmlTag;
467     *password = upload->password;
468 }
469 
470 void
swUploadSetSettings(SUPLOAD upload,const char * commandline,const char * htmlTag,const char * password)471 swUploadSetSettings(SUPLOAD upload,
472                     const char *commandline,
473                     const char *htmlTag,
474                     const char *password)
475 {
476     free(upload->commandline);
477     free(upload->htmlTag);
478 
479     upload->commandline = mystrdup(commandline);
480     upload->htmlTag = mystrdup(htmlTag);
481     if (password != NULL)
482         mystrncpy_secure(upload->password, password, 1023);
483     else
484         upload->password[0] = 0;
485 
486     swSetPreference(upload->prefs, "UploadCommandLine", upload->commandline);
487     swSetPreference(upload->prefs, "UploadHtmlTags", upload->htmlTag);
488     /* do not read/store password for security reasons */
489 }
490 
491 int
swHasUpload(SUPLOAD upload)492 swHasUpload(SUPLOAD upload)
493 {
494     if (strlen(upload->commandline) > 0)
495         return 1;
496     else
497         return 0;
498 }
499 
500 char*
swUpload(SUPLOAD upload,char * fileToUpload,SHBROWSER browser,SWND wnd)501 swUpload(SUPLOAD upload, char *fileToUpload, SHBROWSER browser, SWND wnd)
502 {
503     static char uploadCommand[1024];
504     FILE *cmd;
505     HANDLE f;
506     struct _SECURITY_ATTRIBUTES security_attrib = {
507         sizeof(SECURITY_ATTRIBUTES),
508         NULL,  // default security descriptor of the calling process
509         FALSE
510     };
511     DWORD bytesWritten;
512     static char htmlTags[1024];
513     int needPassword = 0;
514     char *htmlpath = (char *) malloc(1024);
515     htmlpath[0] = 0;
516 
517     if ((upload->password != NULL) && (strlen(upload->password) != 0))
518         if (strstr(upload->commandline, "%s")  !=  NULL)
519             if (strstr(strstr(upload->commandline, "%s") + 2, "%s") !=  NULL)
520                 needPassword = 1; // if commandline has two %s
521     VirtualLock(uploadCommand, 1024);
522     if (needPassword)
523         mysnprintf(uploadCommand, 1023, upload->commandline, upload->password,
524                    fileToUpload);
525     else
526         mysnprintf(uploadCommand, 1023, upload->commandline, fileToUpload, "");
527 
528     if (system(uploadCommand) != 0) {
529         swMessageBox(wnd, "upload failed", "Upload failed",
530                      SW_MB_OK, SW_MB_WARNING);
531         htmlpath[0] = 0;
532         VirtualUnlock(uploadCommand, 1024);
533         return htmlpath;
534     } else
535         VirtualUnlock(uploadCommand, 1024);
536 
537     swGetTempPath(htmlpath, ".dune_upload_reload", ".html", 1024);
538 
539     f = CreateFile(htmlpath,
540                    GENERIC_WRITE,                // open for writing
541                    0,                            // do not share
542                    &security_attrib,             // security attributes
543                    CREATE_NEW,                   // do not overwrite existing
544                    FILE_ATTRIBUTE_NORMAL,        // normal file
545                    NULL);                        // no attr. template
546 
547     if (f == NULL) {
548         char msg[1024];
549         mysnprintf(msg, 1023, "creation of new html file %s failed", htmlpath);
550         swMessageBox(wnd, msg, "Upload reload error", SW_MB_OK, SW_MB_WARNING);
551         htmlpath[0] = 0;
552         return htmlpath;
553     }
554     if ((upload->password != NULL) && (strlen(upload->password) != 0))
555         mysnprintf(htmlTags, 1023, upload->htmlTag, upload->password);
556     else
557         mysnprintf(htmlTags, 1023, upload->htmlTag, "");
558     if (WriteFile(f, htmlTags, sizeof(htmlTags), &bytesWritten,NULL) ==0) {
559         char msg[1024];
560         mysnprintf(msg, 1023, "write to html file %s failed", htmlpath);
561         swMessageBox(wnd, msg, "Upload reload error", SW_MB_OK, SW_MB_WARNING);
562         return htmlpath;
563     }
564     CloseHandle(f);
565     helpBrowserGoTo(browser, htmlpath);
566     return htmlpath;
567 }
568 
569 void
swUploadCleanupPasswd(SUPLOAD upload)570 swUploadCleanupPasswd(SUPLOAD upload)
571 {
572     int i;
573     for (i = 0; i < strlen(upload->password); i++)
574         upload->password[i] = (char) 0;
575     VirtualUnlock(upload->password, 1024);
576 }
577 
578 /* help browser */
579 
580 static void saveHelpBrowserPreferences(SHBROWSER browser);
581 static int getShellOpenHelpCommand(SHBROWSER browser, const char *extension);
582 static int helpBrowserGoTo(SHBROWSER browser, const char *path);
583 static int helpBringToFront(SHBROWSER browser);
584 static int helpBrowserConnect(SHBROWSER browser);
585 
586 typedef struct SHelpBrowser {
587     STABLE prefs;
588     char  *helpCommand;
589     char  *helpRemoteCommand;
590     char  *helpApplication;
591     char  *helpTopic;
592     char  *helpUrl;
593     char  *vrmlUrl;
594     char  *x3dUrl;
595     DWORD  DDEInst;
596     HSZ    ourService;
597     HSZ    theirService;
598     HSZ    topicSZ;
599     HSZ    exitSZ;
600     HANDLE hProcess;
601 } SHBrowser;
602 
603 
swHelpBrowserInit(STABLE prefs)604 SHBROWSER swHelpBrowserInit(STABLE prefs)
605 {
606     SHBrowser *browser = malloc(sizeof(SHBrowser));
607     char *url;
608     const char *index = "index.html";
609     const char *helpDir = HELP_URL;
610 
611     browser->prefs = prefs;
612     browser->helpCommand = mystrdup(swGetPreference(prefs, "HelpCommand", ""));
613     browser->helpRemoteCommand = mystrdup(swGetPreference(prefs,
614                                           "HelpRemoteCommand",""));
615     browser->helpApplication = mystrdup(swGetPreference(prefs,
616 #ifdef _WIN32
617                                         "HelpApplication", DEFAULT_BROWSER));
618 #else
619                                         "HelpApplication", ""));
620 #endif
621     browser->helpTopic = mystrdup(swGetPreference(prefs, "HelpTopic", ""));
622     url = (char *) malloc(strlen(HELP_URL) + strlen(index) + 2);
623     strcpy(url, HELP_URL);
624     if (helpDir[strlen(helpDir - 1)] != '/')
625         strcat(url, "/");
626     strcat(url, index);
627     browser->helpUrl = mystrdup(swGetPreference(prefs, "HelpURL", url));
628     free(url);
629     browser->vrmlUrl = mystrdup(swGetPreference(prefs, "HelpVrml",
630                                                 VRML_NODES_URL));
631     browser->x3dUrl = mystrdup(swGetPreference(prefs, "HelpX3D",
632                                                X3D_URL));
633 
634     if (browser->helpCommand[0]==' ') {
635         getShellOpenHelpCommand(browser, ".htm");
636     } else if (!browser->helpCommand[0]) {
637         getShellOpenHelpCommand(browser, ".htm");
638     }
639 
640     browser->hProcess = NULL;
641     browser->DDEInst = 0L;
642 
643     return browser;
644 }
645 
646 void
swHelpBrowserSetDefaults(SHBROWSER browser)647 swHelpBrowserSetDefaults(SHBROWSER browser)
648 {
649     char *dunedocs = NULL;
650 
651     browser->helpCommand = mystrdup(WWW_BROWSER);
652     dunedocs = getenv("DUNEDOCS");
653     if (dunedocs != NULL) {
654         char *url;
655         url = (char *) malloc(strlen(dunedocs) + /* strlen(html) */ + 1);
656         strcpy(url, dunedocs);
657         browser->helpUrl = mystrdup(url);
658         free(url);
659     } else
660         browser->helpUrl = mystrdup(HELP_URL);
661     browser->vrmlUrl = mystrdup(VRML_NODES_URL);
662     browser->x3dUrl = mystrdup(X3D_URL);
663 }
664 
665 
swHelpBrowserGetSettings(SHBROWSER browser,const char ** helpCommand,const char ** helpRemoteCommand,const char ** helpUrl,const char ** vrmlUrl,const char ** x3dUrl,const char ** helpApplication,const char ** helpTopic)666 void swHelpBrowserGetSettings(SHBROWSER browser,
667                               const char **helpCommand,
668                               const char **helpRemoteCommand,
669                               const char **helpUrl,
670                               const char **vrmlUrl, const char **x3dUrl,
671                               const char **helpApplication,
672                               const char **helpTopic)
673 {
674     *helpCommand = browser->helpCommand;
675     *helpRemoteCommand = browser->helpRemoteCommand;
676     *helpUrl = browser->helpUrl;
677     *vrmlUrl = browser->vrmlUrl;
678     *x3dUrl = browser->x3dUrl;
679     *helpApplication = browser->helpApplication;
680     *helpTopic = browser->helpTopic;
681 }
682 
swHelpBrowserSetSettings(SHBROWSER browser,const char * helpCommand,const char * helpRemoteCommand,const char * helpUrl,const char * vrmlUrl,const char * x3dUrl,const char * helpApplication,const char * helpTopic)683 void swHelpBrowserSetSettings(SHBROWSER browser,
684                               const char *helpCommand,
685                               const char *helpRemoteCommand,
686                               const char *helpUrl,
687                               const char *vrmlUrl, const char *x3dUrl,
688                               const char *helpApplication,
689                               const char *helpTopic)
690 {
691     free(browser->helpCommand);
692     free(browser->helpRemoteCommand);
693     free(browser->helpUrl);
694     free(browser->vrmlUrl);
695     free(browser->x3dUrl);
696     free(browser->helpApplication);
697     free(browser->helpTopic);
698 
699     browser->helpCommand = mystrdup(helpCommand);
700     browser->helpRemoteCommand = mystrdup(helpRemoteCommand);
701     browser->helpUrl = mystrdup(helpUrl);
702     browser->vrmlUrl = mystrdup(vrmlUrl);
703     browser->x3dUrl = mystrdup(vrmlUrl);
704     browser->helpApplication = mystrdup(helpApplication);
705     browser->helpTopic = mystrdup(helpTopic);
706 
707     saveHelpBrowserPreferences(browser);
708 }
709 
710 void
swHelpBrowserX3d(SHBROWSER browser,const char * string,SWND wnd)711 swHelpBrowserX3d(SHBROWSER browser, const char* string, SWND wnd)
712 {
713     int pathLen=strlen(browser->x3dUrl);
714     char *path=malloc(pathLen+strlen(string)+2);
715     strcpy(path,browser->x3dUrl);
716     strcat(path,string);
717     helpBrowserGoTo(browser, path);
718     free(path);
719 }
720 
721 static void
saveHelpBrowserPreferences(SHBROWSER browser)722 saveHelpBrowserPreferences(SHBROWSER browser)
723 {
724     swSetPreference(browser->prefs, "HelpCommand", browser->helpCommand);
725     swSetPreference(browser->prefs, "HelpRemoteCommand", browser->helpRemoteCommand);
726     swSetPreference(browser->prefs, "HelpUrl", browser->helpUrl);
727     swSetPreference(browser->prefs, "HelpVrml", browser->vrmlUrl);
728     swSetPreference(browser->prefs, "HelpX3d", browser->x3dUrl);
729     swSetPreference(browser->prefs, "HelpApplication", browser->helpApplication);
730     swSetPreference(browser->prefs, "HelpTopic", browser->helpTopic);
731 }
732 
swHelpBrowserHTML(SHBROWSER browser,SWND wnd)733 void swHelpBrowserHTML(SHBROWSER browser, SWND wnd)
734 {
735     swHelpBrowserPath(browser,  browser->helpUrl, wnd);
736 }
737 
738 void
swHelpBrowserPath(SHBROWSER browser,const char * path,SWND wnd)739 swHelpBrowserPath(SHBROWSER browser, const char* path, SWND wnd)
740 {
741     if ((strstr(browser->helpCommand, "%s") != NULL) ||
742         (strstr(browser->helpCommand, "%1") != NULL)) {
743         char buf[4096];
744         mysnprintf(buf,4096, browser->helpCommand, path);
745         browserLaunch(buf, browser->hProcess, " ", wnd);
746     } else if (!helpBrowserGoTo(browser, path))
747         if (browserLaunch(browser->helpCommand, browser->hProcess, NULL, wnd)) {
748             helpBrowserGoTo(browser, path);
749     }
750 }
751 
swGetHelpUrl(SHBROWSER browser)752 char *swGetHelpUrl(SHBROWSER browser)
753 {
754     return browser->helpUrl;
755 }
756 
757 void
swHelpBrowserVRML(SHBROWSER browser,const char * selection_string,int isCover,SWND wnd)758 swHelpBrowserVRML(SHBROWSER browser, const char* selection_string,
759                   int isCover, SWND wnd)
760 {
761     int pathLen=strlen(browser->vrmlUrl);
762     const char *coverFile="/coverNodes/nodesRef.html";
763     char* path;
764     if (isCover)
765         pathLen=strlen(browser->helpUrl)+strlen(coverFile)+1;
766     path=malloc(pathLen+strlen(selection_string)+2);
767     if (isCover) {
768         strcpy(path, browser->helpUrl);
769         strcat(path, coverFile);
770     } else
771         strcpy(path,browser->vrmlUrl);
772     strcat(path,"#");
773     strcat(path,selection_string);
774     if (strstr(browser->helpCommand, "%s") != NULL) {
775         char buf[4096];
776         mysnprintf(buf,4096, browser->helpCommand, path);
777         browserLaunch(buf, browser->hProcess, " ", wnd);
778     } else if (!helpBrowserGoTo(browser, path))
779         if (browserLaunch(browser->helpCommand, browser->hProcess, NULL, wnd)) {
780             helpBrowserGoTo(browser, path);
781     }
782     free(path);
783 }
784 
swHelpBrowserShutdown(SHBROWSER browser)785 void swHelpBrowserShutdown(SHBROWSER browser)
786 {
787     saveHelpBrowserPreferences(browser);
788     if (browser->hProcess) {
789         TerminateProcess(browser->hProcess, 1);
790         CloseHandle(browser->hProcess);
791     }
792     free(browser->helpCommand);
793     free(browser->helpRemoteCommand);
794     free(browser->helpUrl);
795     free(browser->vrmlUrl);
796     free(browser->helpApplication);
797     free(browser->helpTopic);
798 
799     if (browser->DDEInst != 0) {
800         DdeNameService(browser->DDEInst, NULL, NULL, DNS_UNREGISTER);
801         DdeFreeStringHandle(browser->DDEInst, browser->theirService);
802         DdeFreeStringHandle(browser->DDEInst, browser->ourService);
803         DdeFreeStringHandle(browser->DDEInst, browser->topicSZ);
804         DdeUninitialize(browser->DDEInst );
805     }
806     free(browser);
807 }
808 
809 static int
getShellOpenHelpCommand(SHBROWSER browser,const char * extension)810 getShellOpenHelpCommand(SHBROWSER browser, const char *extension)
811 {
812     HKEY key;
813     char *info;
814 
815     if (queryValue(HKEY_CLASSES_ROOT, extension, &info) != ERROR_SUCCESS) {
816         return FALSE;
817     }
818 
819     if (RegOpenKey(HKEY_CLASSES_ROOT, info, &key) != ERROR_SUCCESS) {
820         free(info);
821         return FALSE;
822     }
823 
824     free(browser->helpCommand);
825     free(browser->helpApplication);
826     free(browser->helpTopic);
827 
828     queryValue(key, "Shell\\Open\\command", &browser->helpCommand);
829 //    queryValue(key, "Shell\\Open\\ddeexec", &browser->helpRemoteCommand);
830     browser->helpRemoteCommand = mystrdup("%1");
831     queryValue(key, "Shell\\Open\\ddeexec\\Application", &browser->helpApplication);
832     queryValue(key, "Shell\\Open\\ddeexec\\Topic", &browser->helpTopic);
833 
834     RegCloseKey(key);
835     free(info);
836     return TRUE;
837 }
838 
helpBrowserGoTo(SHBROWSER browser,const char * path)839 static int helpBrowserGoTo(SHBROWSER browser, const char *path)
840 {
841     char       *buf;
842 
843     HSZ data;
844     HCONV conv;
845     HDDEDATA res;
846     int timeout = 120;
847     int rc = FALSE;
848 
849     if (browser->DDEInst == 0) {
850         if (!helpBrowserConnect(browser)) return FALSE;
851     }
852     conv = DdeConnect(browser->DDEInst, browser->theirService,
853                       browser->topicSZ, NULL );
854     if (conv != NULL) {
855         buf = fmtMsg( browser->helpRemoteCommand, path );
856         data = DdeCreateStringHandle( browser->DDEInst, buf, CP_WINANSI );
857 
858         res = DdeClientTransaction(NULL, 0, conv, data, CF_TEXT,
859                                    XTYP_REQUEST, TIMEOUT_ASYNC, NULL);
860 
861         DdeDisconnect( conv);
862         DdeFreeStringHandle( browser->DDEInst, data);
863         free(buf);
864         helpBringToFront(browser);
865         rc = TRUE;
866     }
867     return rc;
868 }
869 
870 
helpBringToFront(SHBROWSER browser)871 static int helpBringToFront(SHBROWSER browser)
872 {
873     HSZ data, activate;
874     HCONV conv;
875     int timeout = 120;
876     int rc = FALSE;
877 
878     activate = DdeCreateStringHandle(browser->DDEInst, "WWW_Activate", CP_WINANSI );
879     conv = DdeConnect( browser->DDEInst, browser->theirService, activate, NULL );
880     if (conv != NULL) {
881         data = DdeCreateStringHandle(browser->DDEInst, "0xFFFFFFFF", CP_WINANSI );
882 
883         DdeClientTransaction(NULL, 0, conv, data, CF_TEXT, XTYP_REQUEST,
884                             TIMEOUT_ASYNC, NULL);
885 
886         DdeFreeStringHandle(browser->DDEInst, data);
887         DdeDisconnect( conv);
888         rc = TRUE;
889     }
890     DdeFreeStringHandle(browser->DDEInst, activate);
891     return rc;
892 }
893 
894 static int
helpBrowserConnect(SHBROWSER browser)895 helpBrowserConnect(SHBROWSER browser)
896 {
897     int rc = FALSE;
898 
899     UINT initRes = DdeInitialize(&browser->DDEInst,
900                                  (PFNCALLBACK) DDECallback,
901                                  APPCLASS_STANDARD |
902                                  CBF_FAIL_CONNECTIONS |
903                                  CBF_SKIP_DISCONNECTS,
904                                  0);
905 
906     if (initRes == DMLERR_NO_ERROR) {
907         browser->theirService = DdeCreateStringHandle( browser->DDEInst, browser->helpApplication, CP_WINANSI );
908         browser->ourService = DdeCreateStringHandle( browser->DDEInst, "Dune", CP_WINANSI );
909         browser->topicSZ = DdeCreateStringHandle( browser->DDEInst, browser->helpTopic, CP_WINANSI );
910 
911         DdeNameService( browser->DDEInst, browser->ourService, NULL, DNS_REGISTER);
912          rc = TRUE;
913     }
914     return rc;
915 }
916 
917 
918 /****************/
919 /* text editor */
920 /**************/
921 
922 HANDLE hProcess;
923 
924 int
swCheckRunningProcess(void)925 swCheckRunningProcess(void)
926 {
927     DWORD ExitCode;
928     if (GetExitCodeProcess(hProcess, &ExitCode))
929         if (ExitCode == STILL_ACTIVE)
930             return 1;
931         else {
932              CloseHandle(hProcess);
933             return 0;
934         }
935     else
936         return 0;
937 
938 }
939 
940 int
swCreateCheckableProcess(const char * cmdline)941 swCreateCheckableProcess(const char *cmdline)
942 {
943     STARTUPINFO startInfo;
944     PROCESS_INFORMATION processInfo;
945     SECURITY_ATTRIBUTES securityAttributes;
946     int rc;
947 
948     memset(&startInfo, 0, sizeof(startInfo));
949 
950     startInfo.cb = sizeof(STARTUPINFO);
951     startInfo.dwFlags = STARTF_USESHOWWINDOW;
952     startInfo.wShowWindow = SW_SHOWNA;
953 
954     memset(&securityAttributes, 0, sizeof(securityAttributes));
955 
956     securityAttributes.nLength = sizeof(securityAttributes);
957     securityAttributes.lpSecurityDescriptor = (void*)PROCESS_QUERY_INFORMATION;
958     securityAttributes.bInheritHandle = TRUE;
959 
960      if (CreateProcess(NULL, cmdline, &securityAttributes, NULL, TRUE, 0,
961                        NULL, NULL,
962                        &startInfo, &processInfo) != 0) {
963          WaitForInputIdle(processInfo.hProcess, STARTUP_TIMEOUT );
964          CloseHandle(processInfo.hThread);
965          hProcess = processInfo.hProcess;
966          rc = 0;
967     } else {
968          rc = GetLastError();
969     }
970     return rc;
971 }
972 
973 typedef struct STextedit {
974     STABLE  prefs;
975     char   *textEditCommand;
976     char   *textEditLinenumberOption;
977     int     textEditUseExtensionTxt;
978     char   *imageEditCommand;
979     char   *imageEdit4KidsCommand;
980     char   *soundEditCommand;
981     char   *movieEditCommand;
982 } STextedit;
983 
984 
985 STEXTEDIT
swTextEditInit(STABLE prefs)986 swTextEditInit(STABLE prefs)
987 {
988     STextedit *textEdit = malloc(sizeof(STextedit));
989     textEdit->prefs = prefs;
990     if (getenv("WINEDITOR") != NULL) {
991         textEdit->textEditCommand = mystrdup(swGetPreference(
992               prefs, "TextEditCommand", getenv("WINEDITOR")));
993         textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
994               prefs, "TextEditLinenumberOption", ""));
995     } else {
996         textEdit->textEditCommand = mystrdup(swGetPreference(
997               prefs, "TextEditCommand",
998               "\"C:\\Program Files\\Windows NT\\Accessories\\Wordpad.exe\""));
999         textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
1000               prefs, "TextEditLinenumberOption", " "));
1001     }
1002     textEdit->textEditUseExtensionTxt = swGetIntPreference(
1003           prefs, "TextEditUseExtensionTxt", 1);
1004     textEdit->imageEditCommand = mystrdup(swGetPreference(
1005           prefs, "ImageEditCommand", "C:\\Windows\\system32\\mspaint.exe"));
1006     textEdit->imageEdit4KidsCommand = mystrdup(swGetPreference(
1007           prefs, "ImageEdit4KidsCommand", "C:\\Windows\\system32\\mspaint.exe"));
1008     textEdit->soundEditCommand = mystrdup(swGetPreference(
1009           prefs, "SoundEditCommand", HAVE_SOUND_EDITOR));
1010     textEdit->movieEditCommand = mystrdup(swGetPreference(
1011           prefs, "MovieEditCommand", HAVE_MOVIE_EDITOR));
1012 
1013     return textEdit;
1014 }
1015 
swTextEditGetSettingsUseExtensionTxt(STEXTEDIT textEdit,int * textEditUseExtensionTxt)1016 void swTextEditGetSettingsUseExtensionTxt(STEXTEDIT textEdit,
1017                                           int *textEditUseExtensionTxt)
1018 {
1019     *textEditUseExtensionTxt = textEdit->textEditUseExtensionTxt;
1020 }
1021 
1022 void
swTextEditGetSettings(STEXTEDIT textEdit,const char ** textEditCommand,const char ** textEditLinenumberOption,int * textEditUseExtensionTxt)1023 swTextEditGetSettings(STEXTEDIT textEdit,
1024                       const char **textEditCommand,
1025                       const char **textEditLinenumberOption,
1026                       int *textEditUseExtensionTxt)
1027 {
1028     *textEditCommand = textEdit->textEditCommand;
1029     *textEditLinenumberOption = textEdit->textEditLinenumberOption;
1030     *textEditUseExtensionTxt = textEdit->textEditUseExtensionTxt;
1031 }
1032 
swTextEditGetCommand(STEXTEDIT textEdit)1033 char *swTextEditGetCommand(STEXTEDIT textEdit)
1034 {
1035     return textEdit->textEditCommand;
1036 }
1037 
swImageEditGetSettings(STEXTEDIT textEdit)1038 char *swImageEditGetSettings(STEXTEDIT textEdit)
1039 {
1040     return textEdit->imageEditCommand;
1041 }
1042 
swImageEdit4KidsGetSettings(STEXTEDIT textEdit)1043 char *swImageEdit4KidsGetSettings(STEXTEDIT textEdit)
1044 {
1045     return textEdit->imageEdit4KidsCommand;
1046 }
1047 
swSoundEditGetSettings(STEXTEDIT textEdit)1048 char *swSoundEditGetSettings(STEXTEDIT textEdit)
1049 {
1050     return textEdit->soundEditCommand;
1051 }
1052 
swMovieEditGetSettings(STEXTEDIT textEdit)1053 char *swMovieEditGetSettings(STEXTEDIT textEdit)
1054 {
1055     return textEdit->movieEditCommand;
1056 }
1057 
1058 void
swTextEditSetSettings(STEXTEDIT textEdit,const char * textEditCommand,const char * textEditLinenumberOption,int textEditUseExtensionTxt)1059 swTextEditSetSettings(STEXTEDIT textEdit,
1060                       const char *textEditCommand,
1061                       const char *textEditLinenumberOption,
1062                       int textEditUseExtensionTxt)
1063 {
1064     free(textEdit->textEditCommand);
1065     textEdit->textEditCommand = mystrdup(textEditCommand);
1066 
1067     free(textEdit->textEditLinenumberOption);
1068     textEdit->textEditLinenumberOption = mystrdup(textEditLinenumberOption);
1069 
1070     textEdit->textEditUseExtensionTxt = textEditUseExtensionTxt;
1071 
1072     swSetPreference(textEdit->prefs, "TextEditCommand",
1073                     textEdit->textEditCommand);
1074     swSetPreference(textEdit->prefs, "TextEditLinenumberOption",
1075                     textEdit->textEditLinenumberOption);
1076     swSetIntPreference(textEdit->prefs, "TextEditUseExtensionTxt",
1077                        textEdit->textEditUseExtensionTxt);
1078 
1079     textEdit->imageEditCommand = mystrdup(swGetPreference(
1080           textEdit->prefs, "ImageEditCommand", HAVE_IMAGE_EDITOR));
1081     textEdit->imageEdit4KidsCommand = mystrdup(swGetPreference(
1082           textEdit->prefs, "ImageEdit4KidsCommand", HAVE_IMAGE_EDITOR4KIDS));
1083     textEdit->soundEditCommand = mystrdup(swGetPreference(
1084           textEdit->prefs, "C:\\usr\\bin\\SoundEditCommand.exe", ""));
1085     textEdit->movieEditCommand = mystrdup(swGetPreference(
1086           textEdit->prefs, "C:\\usr\\bin\\movieEditCommand.exe", ""));
1087 }
1088 
1089 void
swImageEditSetSettings(STEXTEDIT textEdit,const char * imageEditCommand)1090 swImageEditSetSettings(STEXTEDIT textEdit,
1091                       const char *imageEditCommand)
1092 {
1093     free(textEdit->imageEditCommand);
1094     textEdit->imageEditCommand = mystrdup(imageEditCommand);
1095     swSetPreference(textEdit->prefs, "ImageEditCommand",
1096                     textEdit->imageEditCommand);
1097 }
1098 
1099 void
swImageEdit4KidsSetSettings(STEXTEDIT textEdit,const char * imageEditCommand)1100 swImageEdit4KidsSetSettings(STEXTEDIT textEdit,
1101                             const char *imageEditCommand)
1102 {
1103     free(textEdit->imageEdit4KidsCommand);
1104     textEdit->imageEdit4KidsCommand = mystrdup(imageEditCommand);
1105     swSetPreference(textEdit->prefs, "ImageEdit4KidsCommand",
1106                     textEdit->imageEdit4KidsCommand);
1107 }
1108 
1109 void
swSoundEditSetSettings(STEXTEDIT textEdit,const char * soundEditCommand)1110 swSoundEditSetSettings(STEXTEDIT textEdit,
1111                       const char *soundEditCommand)
1112 {
1113     free(textEdit->soundEditCommand);
1114     textEdit->soundEditCommand = mystrdup(soundEditCommand);
1115     swSetPreference(textEdit->prefs, "SoundEditCommand",
1116                     textEdit->soundEditCommand);
1117 }
1118 
1119 void
swMovieEditSetSettings(STEXTEDIT textEdit,const char * movieEditCommand)1120 swMovieEditSetSettings(STEXTEDIT textEdit,
1121                        const char *movieEditCommand)
1122 {
1123     free(textEdit->movieEditCommand);
1124     textEdit->movieEditCommand = mystrdup(movieEditCommand);
1125     swSetPreference(textEdit->prefs, "MovieEditCommand",
1126                     textEdit->movieEditCommand);
1127 }
1128 
1129 
1130