1 /*
2 * browser.c - unix interface to web browser
3 *
4 * Copyright (C) 2000 Stephen F. White, 2003 J. "MUFTI" Scheurich
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 #ifdef __sun
23 # define BSD_COMP
24 #endif
25 #include <fcntl.h>
26
27 #include <X11/Intrinsic.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/wait.h>
34
35 #include "config.h"
36
37 #ifdef HAVE_TERM
38 # define TERM HAVE_TERM
39 #else
40 # define TERM "xterm"
41 #endif
42
43 #ifdef HAS_MLOCK
44 # include <sys/mman.h>
45 #endif
46
47 #include "swt.h"
48 #include "mysnprintf.h"
49 #include "WriteFlags.h"
50
51 typedef struct SBrowser {
52 STABLE prefs;
53 char *command;
54 int vrmlLevel;
55 int useFork;
56 int useRemote;
57 char *remoteCommand;
58 pid_t pid;
59 } SBrowser;
60
61 extern XtAppContext TheAppContext;
62
63 static int console = 2;
64
65 static int browserLaunch(SBROWSER browser, const char *path, SWND wnd);
66 static int browserRemote(SBROWSER browser, const char *path);
67 static void childInput(XtPointer closure , int *source, XtInputId *id);
68 static int waitForProcess(pid_t pid);
69 static pid_t createProcess(const char *cmdline, SWND wnd);
70 static pid_t createSimpleProcess(const char *cmdline);
71
72 static int errorToConsole = 1;
73
74 /*******************/
75 /* browser preview */
76 /*******************/
77
78 SBROWSER
swBrowserInit(STABLE prefs)79 swBrowserInit(STABLE prefs)
80 {
81 SBrowser *browser = malloc(sizeof(SBrowser));
82 browser->prefs = prefs;
83 browser->command = mystrdup(swGetPreference(prefs, "PreviewCommand",
84 VRML_BROWSER));
85 browser->useFork = swGetIntPreference(prefs, "PreviewUseFork", FALSE);
86 browser->vrmlLevel = swGetIntPreference(prefs, "PreviewVrmlLevel", X3DOM);
87 browser->useRemote = swGetIntPreference(prefs, "PreviewUseRemote", FALSE);
88 browser->remoteCommand = mystrdup(swGetPreference(prefs,
89 "PreviewRemoteCommand",
90 VRML_REMOTE_BROWSER));
91 browser->pid = 0;
92
93 errorToConsole = swGetIntPreference(prefs, "PreviewErrorToConsole", FALSE);
94
95 console = open("/dev/console", O_WRONLY | O_NONBLOCK);
96 if (console == -1)
97 console = 2;
98
99 return browser;
100 }
101
102 int
swBrowserGetVrmlLevel(SBROWSER browser)103 swBrowserGetVrmlLevel(SBROWSER browser)
104 {
105 return browser->vrmlLevel;
106 }
107
108 int
swBrowserGetRemote(SBROWSER browser)109 swBrowserGetRemote(SBROWSER browser)
110 {
111 return browser->useRemote;
112 }
113
114 void
swBrowserSetRemote(SBROWSER browser,int remote)115 swBrowserSetRemote(SBROWSER browser, int remote)
116 {
117 browser->useRemote = remote;
118 }
119
120 int
swBrowserGetUseFork(SBROWSER browser)121 swBrowserGetUseFork(SBROWSER browser)
122 {
123 return browser->useFork;
124 }
125
126 void
swBrowserGetSettings(SBROWSER browser,const char ** command,int * vrmlLevel,int * useRemote,int * useFork,const char ** remoteCommand,const char ** application,const char ** topic)127 swBrowserGetSettings(SBROWSER browser, const char **command,
128 int* vrmlLevel, int *useRemote, int *useFork,
129 const char **remoteCommand, const char **application,
130 const char **topic)
131 {
132 *command = browser->command;
133 *vrmlLevel = browser->vrmlLevel;
134 *useRemote = browser->useRemote;
135 *useFork = browser->useFork;
136 *remoteCommand = browser->remoteCommand;
137 *application = NULL;
138 *topic = NULL;
139 }
140
141 void
swBrowserSetSettings(SBROWSER browser,const char * command,int vrmlLevel,int useRemote,int useFork,const char * remoteCommand,const char * application,const char * topic)142 swBrowserSetSettings(SBROWSER browser, const char *command,
143 int vrmlLevel, int useRemote, int useFork,
144 const char *remoteCommand, const char *application,
145 const char *topic)
146 {
147 char *oldCommand = mystrdup(command);
148 char *oldRemoteCommand = mystrdup(remoteCommand);
149 free(browser->command);
150 free(browser->remoteCommand);
151
152 browser->command = oldCommand;
153 browser->vrmlLevel = vrmlLevel;
154 browser->useRemote = useRemote;
155 browser->useFork = useFork;
156 browser->remoteCommand = oldRemoteCommand;
157
158 swSetPreference(browser->prefs, "PreviewCommand", browser->command);
159 swSetIntPreference(browser->prefs, "PreviewUseRemote", browser->useRemote);
160 swSetIntPreference(browser->prefs, "PreviewVrmlLevel", browser->vrmlLevel);
161 swSetIntPreference(browser->prefs, "PreviewUseFork", browser->useFork);
162 swSetPreference(browser->prefs, "PreviewRemoteCommand", browser->remoteCommand);
163 }
164
swBrowserGetSettingsErrorToConsole(SBROWSER browser)165 int swBrowserGetSettingsErrorToConsole(SBROWSER browser)
166 {
167 return errorToConsole;
168 }
169
swBrowserSetSettingsErrorToConsole(SBROWSER browser,int toConsole)170 void swBrowserSetSettingsErrorToConsole(SBROWSER browser, int toConsole)
171 {
172 errorToConsole = toConsole;
173 swSetIntPreference(browser->prefs, "PreviewErrorToConsole", errorToConsole);
174 }
175
176 void
swBrowserSetDefault(SBROWSER browser)177 swBrowserSetDefault(SBROWSER browser)
178 {
179 browser->command = mystrdup(VRML_BROWSER);
180 #ifdef VRML_REMOTE
181 browser->useRemote = TRUE;
182 #else
183 browser->useRemote = FALSE;
184 #endif
185 browser->vrmlLevel = X3DOM;
186 browser->useFork = TRUE;
187 browser->remoteCommand = mystrdup(VRML_REMOTE_BROWSER);
188 browser->pid = 0;
189 }
190
191 void
swBrowserPreview(SBROWSER browser,const char * path,SWND wnd)192 swBrowserPreview(SBROWSER browser, const char *path, SWND wnd)
193 {
194 if (browser->useRemote) {
195 if (!browserRemote(browser, path)) {
196 browserLaunch(browser, path, wnd);
197 }
198 } else {
199 browserLaunch(browser, path, wnd);
200 }
201 }
202
203 void
swBrowserShutdown(SBROWSER browser)204 swBrowserShutdown(SBROWSER browser)
205 {
206 if (!browser) return;
207
208 if (browser->pid != 0) {
209 kill(browser->pid, SIGTERM);
210 waitForProcess(browser->pid);
211 }
212 free(browser->command);
213 free(browser->remoteCommand);
214 free(browser);
215 }
216
217 static int
browserLaunch(SBROWSER browser,const char * path,SWND wnd)218 browserLaunch(SBROWSER browser, const char *path, SWND wnd)
219 {
220 char arg[1024];
221
222 mysnprintf(arg, 1023, browser->command, path);
223 if (browser->useFork) {
224 browser->pid = createProcess(arg, wnd);
225 if (browser->pid != 0)
226 return TRUE;
227 else
228 return FALSE;
229 } else
230 return system(arg);
231 }
232
233 static int
browserRemote(SBROWSER browser,const char * path)234 browserRemote(SBROWSER browser, const char *path)
235 {
236 char url[1024];
237 char arg[1024];
238 pid_t pid;
239 int ret;
240 int i;
241
242 mysnprintf(url, 1023, "file://%s", path);
243 mysnprintf(arg, 1023, browser->remoteCommand, url);
244 pid = createSimpleProcess(arg);
245 ret = waitForProcess(pid);
246 if (!ret) {
247 for (i = 0; (browser->remoteCommand[i] != ' ') &&
248 (browser->remoteCommand[i] != 0) && (i < 1023); i++)
249 arg[i] = browser->remoteCommand[i];
250 arg[i] = ' ';
251 arg[i + 1] = 0;
252 mysnprintf(arg + i + 1, 1023 - i, url);
253 if (i != 0) {
254 pid = createSimpleProcess(arg);
255 ret = waitForProcess(pid);
256 }
257 }
258 return ret;
259 }
260
261 static pid_t
createProcess(const char * cmdline,SWND wnd)262 createProcess(const char *cmdline, SWND wnd)
263 {
264 pid_t pid;
265 int fd[2];
266 const char *argv[4];
267
268 if (!cmdline || !wnd) return 0;
269
270 argv[0] = "sh";
271 argv[1] = "-c";
272 argv[2] = cmdline;
273 argv[3] = NULL;
274
275 if (pipe(fd) != 0) return 0;
276
277 pid = fork();
278 switch(pid) {
279 case -1:
280 /* error */
281 close(fd[0]);
282 close(fd[1]);
283 return 0;
284 case 0:
285 /* child process */
286 if (fd[1] != STDERR_FILENO) {
287 dup2(fd[1], STDERR_FILENO); /* pipe output is now stderr */
288 close(fd[1]); /* close old pipe fds */
289 }
290 close(fd[0]);
291 execv("/bin/sh", (char * const *) argv);
292 swCleanup();
293 exit(1); /* if we get this far, it's an error */
294 default:
295 /* parent process */
296 /* add fd[0] to list of inputs, so we can watch the shell's output */
297 // XtAppAddInput(TheAppContext, fd[0], (XtPointer) XtInputReadMask,
298 // childInput, (XtPointer) wnd);
299 /* close(fd[1]); */
300 break;
301 }
302 return pid;
303 }
304
305 static pid_t
createSimpleProcess(const char * cmdline)306 createSimpleProcess(const char *cmdline)
307 {
308 pid_t pid;
309 const char *argv[4];
310
311 if (!cmdline) return 0;
312
313 argv[0] = "sh";
314 argv[1] = "-c";
315 argv[2] = cmdline;
316 argv[3] = NULL;
317 pid = fork();
318 switch(pid) {
319 case -1:
320 /* error */
321 return 0;
322 case 0:
323 /* child process */
324 execv("/bin/sh", (char * const *) argv);
325 swCleanup();
326 exit(1); /* if we get this far, it's an error */
327 default:
328 /* parent process */
329 break;
330 }
331 return pid;
332 }
333
334 static void
childInput(XtPointer closure,int * source,XtInputId * id)335 childInput(XtPointer closure , int *source, XtInputId *id)
336 {
337 char buf[1024];
338 int bytes;
339
340 bytes = read(*source, buf, 1023);
341 buf[bytes] = '\0';
342 if (errorToConsole)
343 mywritestr(console, buf);
344 else
345 swMessageBox((SWND) closure, buf, "Preview", SW_MB_OK, SW_MB_WARNING);
346 }
347
348 static int
waitForProcess(pid_t pid)349 waitForProcess(pid_t pid)
350 {
351 int status;
352
353 for (;;) {
354 if (waitpid(pid, &status, 0) == -1) {
355 if (errno != EINTR)
356 return 0;
357 } else {
358 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
359 }
360 }
361 }
362
swRemoveFile(const char * filename)363 void swRemoveFile(const char* filename)
364 {
365 unlink(filename);
366 }
367
368 /*****************/
369 /* help browser */
370 /*****************/
371
372 typedef struct SHelpBrowser {
373 STABLE prefs;
374 char *helpCommand;
375 char *helpUrl;
376 char *vrmlUrl;
377 char *x3dUrl;
378 pid_t pid;
379 } SHelpBrowser;
380
381 int helpBrowserRemote(SHBROWSER browser, const char *path, SWND wnd);
382
383 SHBROWSER
swHelpBrowserInit(STABLE prefs)384 swHelpBrowserInit(STABLE prefs)
385 {
386 char *dunedocs = NULL;
387 SHelpBrowser *browser = malloc(sizeof(SHelpBrowser));
388 browser->prefs = prefs;
389 browser->helpCommand = mystrdup(swGetPreference(prefs,"HelpCommand",
390 WWW_BROWSER));
391 dunedocs = getenv("DUNEDOCS");
392 if (dunedocs != NULL) {
393 char *url;
394 url = (char *) malloc(strlen(dunedocs) + /* strlen(html) */ + 1);
395 strcpy(url, dunedocs);
396 browser->helpUrl = mystrdup(swGetPreference(prefs, "HelpURL", url));
397 free(url);
398 } else {
399 char *url;
400 const char *index = "index.html";
401 const char *helpDir = HELP_URL;
402 int helpDirLen;
403 url = (char *) malloc(strlen(HELP_URL) + strlen(index) + 2);
404 strcpy(url, HELP_URL);
405 helpDirLen = strlen(helpDir);
406 if (helpDirLen > 0)
407 if (helpDir[helpDirLen - 1] != '/')
408 strcat(url, "/");
409 strcat(url, index);
410 browser->helpUrl = mystrdup(swGetPreference(prefs, "HelpURL", url));
411 free(url);
412 }
413 browser->vrmlUrl = mystrdup(swGetPreference(prefs, "HelpVrml",
414 VRML_NODES_URL));
415 browser->x3dUrl = mystrdup(swGetPreference(prefs, "HelpX3D",
416 X3D_URL));
417
418 browser->pid = 0;
419
420 return browser;
421 }
422
423 void
swHelpBrowserSetDefaults(SHBROWSER browser)424 swHelpBrowserSetDefaults(SHBROWSER browser)
425 {
426 char *dunedocs = NULL;
427
428 browser->helpCommand = mystrdup(WWW_BROWSER);
429 dunedocs = getenv("DUNEDOCS");
430 if (dunedocs != NULL) {
431 char *url;
432 url = (char *) malloc(strlen(dunedocs) + /* strlen(html) */ + 1);
433 strcpy(url, dunedocs);
434 browser->helpUrl = mystrdup(url);
435 free(url);
436 } else
437 browser->helpUrl = mystrdup(HELP_URL);
438 browser->vrmlUrl = mystrdup(VRML_NODES_URL);
439 browser->x3dUrl = mystrdup(X3D_URL);
440
441 browser->pid = 0;
442 }
443
444 void
swHelpBrowserGetSettings(SHBROWSER browser,const char ** helpCommand,const char ** helpRemoteCommand,const char ** helpUrl,const char ** vrmlUrl,const char ** x3dUrl,const char ** application,const char ** topic)445 swHelpBrowserGetSettings(SHBROWSER browser,
446 const char **helpCommand,
447 const char **helpRemoteCommand,
448 const char **helpUrl,
449 const char **vrmlUrl, const char **x3dUrl,
450 const char **application, const char **topic)
451 {
452 *helpCommand = browser->helpCommand;
453 *helpUrl = browser->helpUrl;
454 *vrmlUrl = browser->vrmlUrl;
455 *x3dUrl = browser->x3dUrl;
456 *application = NULL;
457 *topic = NULL;
458 }
459
460 void
swHelpBrowserSetSettings(SHBROWSER browser,const char * helpCommand,const char * helpRemoteCommand,const char * helpUrl,const char * vrmlUrl,const char * x3dUrl,const char * application,const char * topic)461 swHelpBrowserSetSettings(SHBROWSER browser,
462 const char *helpCommand,
463 const char *helpRemoteCommand,
464 const char *helpUrl,
465 const char *vrmlUrl, const char *x3dUrl,
466 const char *application, const char *topic)
467 {
468 free(browser->helpCommand);
469 browser->helpCommand = mystrdup(helpCommand);
470
471 free(browser->helpUrl);
472 browser->helpUrl = mystrdup(helpUrl);
473
474 free(browser->vrmlUrl);
475 browser->vrmlUrl = mystrdup(vrmlUrl);
476
477 free(browser->x3dUrl);
478 browser->x3dUrl = mystrdup(vrmlUrl);
479
480 swSetPreference(browser->prefs, "HelpCommand", browser->helpCommand);
481 swSetPreference(browser->prefs, "HelpURL", browser->helpUrl);
482 swSetPreference(browser->prefs, "HelpVrml", browser->vrmlUrl);
483 swSetPreference(browser->prefs, "HelpX3d", browser->x3dUrl);
484 }
485
486 void
swHelpBrowserHTML(SHBROWSER browser,SWND wnd)487 swHelpBrowserHTML(SHBROWSER browser, SWND wnd)
488 {
489 char* path=browser->helpUrl;
490
491 helpBrowserRemote(browser, path, wnd);
492 }
493
swGetHelpUrl(SHBROWSER browser)494 char *swGetHelpUrl(SHBROWSER browser)
495 {
496 return browser->helpUrl;
497 }
498
499 void
swHelpBrowserPath(SHBROWSER browser,const char * path,SWND wnd)500 swHelpBrowserPath(SHBROWSER browser, const char *path, SWND wnd)
501 {
502 helpBrowserRemote(browser, path, wnd);
503 }
504
505
506 void
swHelpBrowserVRML(SHBROWSER browser,const char * selection_string,int isCover,SWND wnd)507 swHelpBrowserVRML(SHBROWSER browser, const char* selection_string,
508 int isCover, SWND wnd)
509 {
510 int pathLen=strlen(browser->vrmlUrl);
511 const char *coverFile="/coverNodes/nodesRef.html";
512 char* path;
513 if (isCover)
514 pathLen=strlen(browser->helpUrl)+strlen(coverFile)+1;
515 path=malloc(pathLen+strlen(selection_string)+2);
516 if (isCover) {
517 strcpy(path, browser->helpUrl);
518 strcat(path, coverFile);
519 } else
520 strcpy(path,browser->vrmlUrl);
521 strcat(path,"#");
522 strcat(path,selection_string);
523 helpBrowserRemote(browser, path , wnd);
524 free(path);
525 }
526
527 void
swHelpBrowserX3d(SHBROWSER browser,const char * string,SWND wnd)528 swHelpBrowserX3d(SHBROWSER browser, const char* string, SWND wnd)
529 {
530 int pathLen=strlen(browser->x3dUrl);
531 char *path=malloc(pathLen+strlen(string)+2);
532 strcpy(path,browser->x3dUrl);
533 strcat(path,string);
534 helpBrowserRemote(browser, path , wnd);
535 free(path);
536 }
537
538 void
swHelpBrowserShutdown(SHBROWSER browser)539 swHelpBrowserShutdown(SHBROWSER browser)
540 {
541 if (!browser) return;
542
543 if (browser->pid != 0) {
544 kill(browser->pid, SIGTERM);
545 waitForProcess(browser->pid);
546 }
547 free(browser->helpCommand);
548 free(browser->helpUrl);
549 free(browser->vrmlUrl);
550 free(browser->x3dUrl);
551 free(browser);
552 }
553
554 int
helpBrowserRemote(SHBROWSER browser,const char * path,SWND wnd)555 helpBrowserRemote(SHBROWSER browser, const char *path, SWND wnd)
556 {
557 char url[1024];
558 char arg[1024];
559 char command[1024];
560 pid_t pid;
561 int i;
562
563 if (path[0] == '/')
564 mysnprintf(url, 1023, "file://%s", path);
565 else
566 mysnprintf(url, 1023, path);
567 mysnprintf(arg, 1023, browser->helpCommand, url);
568 pid = createSimpleProcess(arg);
569 /* if failed, search first string (till blank) as command */
570 if (waitForProcess(pid)==0) {
571 for (i=0;(i<strlen(browser->helpCommand)) && (i<1024-3);i++) {
572 command[i]=browser->helpCommand[i];
573 if ((browser->helpCommand[i] !=' ') &&
574 (browser->helpCommand[i+1]==' ')) {
575 i++;
576 break;
577 }
578 }
579 command[i]=0;
580 strcat(command," %s");
581 mysnprintf(arg, 1024, command, path);
582 browser->pid = createProcess(arg, wnd);
583 }
584 if (browser->pid != 0) {
585 return TRUE;
586 } else {
587 return FALSE;
588 }
589 }
590
591
592 /****************/
593 /* text editor */
594 /**************/
595
596 static int fdpipe_message[2];
597 static int fdpipe_close[2];
598
599 int
swCheckRunningProcess(void)600 swCheckRunningProcess(void)
601 {
602 char message[2] = { 'l' , '\0' };
603 /* check if there is something in the pipe (process ended) */
604 int byteFromPipe = 0;
605 if (read(fdpipe_message[0],message,1) == 1)
606 byteFromPipe = 1;
607 if (byteFromPipe) {
608 while (write(fdpipe_close[1], message, 1) == -1)
609 /*
610 send notification to other process
611 (otherwise data possibly would die with close of pipe)
612 */
613 close(fdpipe_close[1]);
614 close(fdpipe_message[0]);
615
616 }
617 return !byteFromPipe;
618 }
619
620 int
swCreateCheckableProcess(const char * cmdline)621 swCreateCheckableProcess(const char *cmdline)
622 {
623 char message[2] = { 'l' , '\0' };
624 pid_t pid;
625
626 if (pipe(fdpipe_message) != 0) return -1;
627
628 if (pipe(fdpipe_close) != 0) {
629 close(fdpipe_message[0]);
630 close(fdpipe_message[1]);
631 return -1;
632 }
633
634 /* switch to non blocking io for pipe of first message */
635 fcntl(fdpipe_message[0],F_SETFL,O_NONBLOCK);
636 fcntl(fdpipe_message[1],F_SETFL,O_NONBLOCK);
637
638 pid = fork();
639 switch(pid) {
640 case -1:
641 /* error */
642 close(fdpipe_message[0]);
643 close(fdpipe_message[1]);
644 close(fdpipe_close[0]);
645 close(fdpipe_close[1]);
646 return -1;
647 case 0:
648 /* child process */
649 close(fdpipe_message[0]);
650 close(fdpipe_close[1]);
651 if (system(cmdline)!=0) {
652 if (fprintf(stderr,"failed: %s\n",cmdline)==0) {}
653 }
654 /* send message to pipe */
655 while (write(fdpipe_message[1],message,1)==-1);
656 /* wait for notification */
657 while (read(fdpipe_close[0],message,1)==-1);
658 close(fdpipe_message[1]);
659 close(fdpipe_close[0]);
660 #ifdef EXIT_HANDLER
661 _exit(0);
662 #else
663 exit(0);
664 #endif
665 default:
666 /* parent process */
667 close(fdpipe_message[1]);
668 close(fdpipe_close[0]);
669 break;
670 }
671 return 0;
672 }
673
674 typedef struct STextedit {
675 STABLE prefs;
676 char *textEditCommand;
677 char *textEditLinenumberOption;
678 int textEditUseExtensionTxt;
679 char *imageEditCommand;
680 char *imageEdit4KidsCommand;
681 char *soundEditCommand;
682 char *movieEditCommand;
683 } STextedit;
684
685
686 STEXTEDIT
swTextEditInit(STABLE prefs)687 swTextEditInit(STABLE prefs)
688 {
689 char *editor = NULL;
690 STextedit *textEdit = malloc(sizeof(STextedit));
691 textEdit->prefs = prefs;
692
693 if (getenv("WINEDITOR") != NULL) {
694 textEdit->textEditCommand = mystrdup(swGetPreference(
695 prefs, "TextEditCommand", getenv("WINEDITOR")));
696 textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
697 prefs, "TextEditLinenumberOption", "+"));
698 } else if (getenv("EDITOR") != NULL) {
699 editor = getenv("EDITOR");
700 textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
701 prefs, "TextEditLinenumberOption", "+"));
702 } else {
703 #ifndef MACOSX
704 editor = "vi";
705 textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
706 prefs, "TextEditLinenumberOption", "+"));
707 #else
708 /*
709 typical MacOS X users would die if they should use vi,
710 but the normal MacOS X textEditor:
711 "/usr/bin/open /Applications/TextEdit.app"
712 is useless here, cause it can not wait for the completion of editing
713 */
714 textEdit->textEditCommand = mystrdup(swGetPreference(
715 prefs, "TextEditCommand", "/usr/X11R6/bin/xedit"));
716 textEdit->textEditLinenumberOption = mystrdup(swGetPreference(
717 prefs, "TextEditLinenumberOption", ""));
718 #endif
719 }
720 #ifdef HAVE_X11_EDITOR
721 textEdit->textEditCommand = mystrdup(swGetPreference(prefs,
722 "TextEditCommand", HAVE_X11_EDITOR));
723 #else
724 if (editor != NULL) {
725 const char *term = TERM;
726 const char *executeoption = " -e ";
727 char *command;
728 command = (char *) malloc(strlen(term) + strlen(executeoption) +
729 strlen(editor) + 1);
730 strcpy(command, term);
731 strcat(command, executeoption);
732 strcat(command, editor);
733
734 textEdit->textEditCommand = mystrdup(swGetPreference(prefs,
735 "TextEditCommand", command));
736 }
737 #endif
738 textEdit->textEditUseExtensionTxt = swGetIntPreference(
739 prefs, "TextEditUseExtensionTxt", 1);
740 textEdit->imageEditCommand = mystrdup(swGetPreference(
741 prefs, "ImageEditCommand", HAVE_IMAGE_EDITOR));
742 textEdit->imageEdit4KidsCommand = mystrdup(swGetPreference(
743 prefs, "ImageEdit4KidsCommand", HAVE_IMAGE_EDITOR4KIDS));
744 textEdit->soundEditCommand = mystrdup(swGetPreference(
745 prefs, "SoundEditCommand", HAVE_SOUND_EDITOR));
746 textEdit->movieEditCommand = mystrdup(swGetPreference(
747 prefs, "MovieEditCommand", HAVE_MOVIE_EDITOR));
748
749 return textEdit;
750 }
751
swTextEditGetSettingsUseExtensionTxt(STEXTEDIT textEdit,int * textEditUseExtensionTxt)752 void swTextEditGetSettingsUseExtensionTxt(STEXTEDIT textEdit,
753 int *textEditUseExtensionTxt)
754 {
755 *textEditUseExtensionTxt = textEdit->textEditUseExtensionTxt;
756 }
757
758 void
swTextEditGetSettings(STEXTEDIT textEdit,const char ** textEditCommand,const char ** textEditLinenumberOption,int * textEditUseExtensionTxt)759 swTextEditGetSettings(STEXTEDIT textEdit,
760 const char **textEditCommand,
761 const char **textEditLinenumberOption,
762 int *textEditUseExtensionTxt)
763 {
764 *textEditCommand = textEdit->textEditCommand;
765 *textEditLinenumberOption = textEdit->textEditLinenumberOption;
766 *textEditUseExtensionTxt = textEdit->textEditUseExtensionTxt;
767 }
768
swTextEditGetCommand(STEXTEDIT textEdit)769 char *swTextEditGetCommand(STEXTEDIT textEdit)
770 {
771 return textEdit->textEditCommand;
772 }
773
swImageEditGetSettings(STEXTEDIT textEdit)774 char *swImageEditGetSettings(STEXTEDIT textEdit)
775 {
776 return textEdit->imageEditCommand;
777 }
778
swImageEdit4KidsGetSettings(STEXTEDIT textEdit)779 char *swImageEdit4KidsGetSettings(STEXTEDIT textEdit)
780 {
781 return textEdit->imageEdit4KidsCommand;
782 }
783
swSoundEditGetSettings(STEXTEDIT textEdit)784 char *swSoundEditGetSettings(STEXTEDIT textEdit)
785 {
786 return textEdit->soundEditCommand;
787 }
788
swMovieEditGetSettings(STEXTEDIT textEdit)789 char *swMovieEditGetSettings(STEXTEDIT textEdit)
790 {
791 return textEdit->movieEditCommand;
792 }
793
794 void
swTextEditSetSettings(STEXTEDIT textEdit,const char * textEditCommand,const char * textEditLinenumberOption,int textEditUseExtensionTxt)795 swTextEditSetSettings(STEXTEDIT textEdit,
796 const char *textEditCommand,
797 const char *textEditLinenumberOption,
798 int textEditUseExtensionTxt)
799 {
800 free(textEdit->textEditCommand);
801 textEdit->textEditCommand = mystrdup(textEditCommand);
802
803 free(textEdit->textEditLinenumberOption);
804 textEdit->textEditLinenumberOption = mystrdup(textEditLinenumberOption);
805
806 textEdit->textEditUseExtensionTxt = textEditUseExtensionTxt;
807
808 swSetPreference(textEdit->prefs, "TextEditCommand",
809 textEdit->textEditCommand);
810 swSetPreference(textEdit->prefs, "TextEditLinenumberOption",
811 textEdit->textEditLinenumberOption);
812 swSetIntPreference(textEdit->prefs, "TextEditUseExtensionTxt",
813 textEdit->textEditUseExtensionTxt);
814 }
815
816 void
swImageEditSetSettings(STEXTEDIT textEdit,const char * imageEditCommand)817 swImageEditSetSettings(STEXTEDIT textEdit,
818 const char *imageEditCommand)
819 {
820 free(textEdit->imageEditCommand);
821 textEdit->imageEditCommand = mystrdup(imageEditCommand);
822 swSetPreference(textEdit->prefs, "ImageEditCommand",
823 textEdit->imageEditCommand);
824 }
825
826 void
swImageEdit4KidsSetSettings(STEXTEDIT textEdit,const char * imageEditCommand)827 swImageEdit4KidsSetSettings(STEXTEDIT textEdit,
828 const char *imageEditCommand)
829 {
830 free(textEdit->imageEdit4KidsCommand);
831 textEdit->imageEdit4KidsCommand = mystrdup(imageEditCommand);
832 swSetPreference(textEdit->prefs, "ImageEdit4KidsCommand",
833 textEdit->imageEdit4KidsCommand);
834 }
835
836 void
swSoundEditSetSettings(STEXTEDIT textEdit,const char * soundEditCommand)837 swSoundEditSetSettings(STEXTEDIT textEdit,
838 const char *soundEditCommand)
839 {
840 free(textEdit->soundEditCommand);
841 textEdit->soundEditCommand = mystrdup(soundEditCommand);
842 swSetPreference(textEdit->prefs, "SoundEditCommand",
843 textEdit->soundEditCommand);
844 }
845
846 void
swMovieEditSetSettings(STEXTEDIT textEdit,const char * movieEditCommand)847 swMovieEditSetSettings(STEXTEDIT textEdit,
848 const char *movieEditCommand)
849 {
850 free(textEdit->movieEditCommand);
851 textEdit->movieEditCommand = mystrdup(movieEditCommand);
852 swSetPreference(textEdit->prefs, "MovieEditCommand",
853 textEdit->movieEditCommand);
854 }
855
856
857 /**********/
858 /* upload */
859 /**********/
860
861 typedef struct SUpload {
862 STABLE prefs;
863 char *commandline;
864 char *htmlTag;
865 char *password;
866 } SUpload;
867
868 SUPLOAD
swUploadInit(STABLE prefs)869 swUploadInit(STABLE prefs)
870 {
871 SUpload *upload = malloc(sizeof(SUpload));
872 upload->prefs = prefs;
873 upload->commandline = mystrdup(swGetPreference(prefs, "UploadCommandLine",
874 ""));
875 upload->htmlTag = mystrdup(swGetPreference(prefs, "UploadHtmlTags",
876 ""));
877 /* do not read/store password for security reasons */
878 upload->password = malloc(1024);
879 upload->password[0] = 0;
880 #ifdef HAS_MLOCK
881 mlock(upload->password, 1024);
882 #endif
883 return upload;
884 }
885
886 void
swUploadGetSettings(SUPLOAD upload,const char ** commandline,const char ** htmlTag,const char ** password)887 swUploadGetSettings(SUPLOAD upload,
888 const char **commandline,
889 const char **htmlTag,
890 const char **password)
891 {
892 *commandline = upload->commandline;
893 *htmlTag = upload->htmlTag;
894 *password = upload->password;
895 }
896
897 void
swUploadSetSettings(SUPLOAD upload,const char * commandline,const char * htmlTag,const char * password)898 swUploadSetSettings(SUPLOAD upload,
899 const char *commandline,
900 const char *htmlTag,
901 const char *password)
902 {
903 free(upload->commandline);
904 free(upload->htmlTag);
905
906 upload->commandline = mystrdup(commandline);
907 upload->htmlTag = mystrdup(htmlTag);
908 if (password != NULL)
909 mystrncpy_secure(upload->password, password, 1023);
910 else
911 upload->password[0] = 0;
912
913 swSetPreference(upload->prefs, "UploadCommandLine", upload->commandline);
914 swSetPreference(upload->prefs, "UploadHtmlTags", upload->htmlTag);
915 /* do not read/store password for security reasons */
916 }
917
918 int
swHasUpload(SUPLOAD upload)919 swHasUpload(SUPLOAD upload)
920 {
921 if (strlen(upload->commandline) > 0)
922 return 1;
923 else
924 return 0;
925 }
926
927 char*
swUpload(SUPLOAD upload,char * fileToUpload,SHBROWSER browser,SWND wnd)928 swUpload(SUPLOAD upload, char *fileToUpload, SHBROWSER browser, SWND wnd)
929 {
930 static char uploadCommand[1024];
931 FILE *cmd;
932 int f = -1;
933 int i;
934 int needPassword = 0;
935 static char htmlTags[1024];
936 char *htmlpath = (char *) malloc(1024);
937 htmlpath[0] = 0;
938
939 if ((upload->password != NULL) && (strlen(upload->password) != 0))
940 if (strstr(upload->commandline, "%s") != NULL)
941 if (strstr(strstr(upload->commandline, "%s") + 2, "%s") != NULL)
942 needPassword = 1; /* if commandline has two %s */
943 #ifdef HAS_MLOCK
944 mlock(uploadCommand, 1024);
945 #endif
946 if (needPassword)
947 mysnprintf(uploadCommand, 1023, upload->commandline, upload->password,
948 fileToUpload);
949 else
950 mysnprintf(uploadCommand, 1023, upload->commandline, fileToUpload, "");
951
952 if ((cmd = popen(uploadCommand, "w")) != NULL) {
953 if ((upload->password != NULL) && (strlen(upload->password) != 0))
954 fputs(upload->password, cmd);
955 if (pclose(cmd) != 0) {
956 swMessageBox(wnd, "upload failed", "Upload failed",
957 SW_MB_OK, SW_MB_WARNING);
958 htmlpath[0] = 0;
959 return htmlpath;
960 }
961 }
962
963 swGetTempPath(htmlpath, ".dune_upload_reload", ".html", 1024);
964 f = open(htmlpath, O_WRONLY | O_CREAT, 00666);
965 if (f == -1) {
966 swMessageBox(wnd, "open of html file failed", "Upload reload error",
967 SW_MB_OK, SW_MB_WARNING);
968 htmlpath[0] = 0;
969 return htmlpath;
970 }
971 if ((upload->password != NULL) && (strlen(upload->password) != 0))
972 mysnprintf(htmlTags, 1023, upload->htmlTag, upload->password);
973 else
974 mysnprintf(htmlTags, 1023, upload->htmlTag, "");
975 if (write(f, htmlTags, sizeof(htmlTags)) != sizeof(htmlTags)) {
976 swMessageBox(wnd, "open of html file failed", "Upload reload error",
977 SW_MB_OK, SW_MB_WARNING);
978 return htmlpath;
979 }
980 close(f);
981 helpBrowserRemote(browser, htmlpath, wnd);
982 for (i = 0; i < 1024; i++)
983 uploadCommand[i] = (char) 0;
984 #ifdef HAS_MLOCK
985 munlock(uploadCommand, 1024);
986 #endif
987 return htmlpath;
988 }
989
990 void
swUploadCleanupPasswd(SUPLOAD upload)991 swUploadCleanupPasswd(SUPLOAD upload)
992 {
993 int i;
994 for (i = 0; i < strlen(upload->password); i++)
995 upload->password[i] = (char) 0;
996 #ifdef HAS_MLOCK
997 munlock(upload->password, 1024);
998 #endif
999 }
1000