1 /*
2  * $LynxId: LYUpload.c,v 1.41 2021/07/29 20:32:26 tom Exp $
3  *
4  *  Routines to upload files to the local filesystem.
5  *  Created by: Rick Mallett, Carleton University
6  *  Report problems to rmallett@ccs.carleton.ca
7  *  Modified 15-Dec-95 George Lindholm (lindholm@ucs.ubc.ca):
8  *	Reread the upload menu page every time, in case the "upload" directory
9  *	  has changed (make the current directory that for the upload process).
10  *	Prompt for the upload file name if there is no "%s" in the command
11  *	  string.  Most protocols allow the user to specify the file name
12  *	  from the client side.  Xmodem appears to be the only that can't
13  *	  figure out the filename from the transfer data so it needs the
14  *	  information from lynx (or an upload script which prompts for it).
15  *	  On the other hand, zmodem aborts when you give it a filename on
16  *	  the command line (great way of bypassing the nodotfile code :=( ).
17  */
18 
19 #include <HTUtils.h>
20 #include <HTFile.h>
21 #include <HTParse.h>
22 #include <HTAlert.h>
23 #include <LYCurses.h>
24 #include <LYUtils.h>
25 #include <LYGlobalDefs.h>
26 #include <LYStrings.h>
27 #include <LYClean.h>
28 #include <LYGetFile.h>
29 #include <LYUpload.h>
30 #include <LYLocal.h>
31 
32 #include <LYexit.h>
33 #include <LYLeaks.h>
34 
35 #define SUBDIR_COMMAND "cd %s ; "
36 
37 /*
38  * LYUpload uploads a file to a given location using a specified upload method.
39  * It parses an incoming link that looks like:
40  *	LYNXDIRED://UPLOAD=<#>/TO=<STRING>
41  */
LYUpload(char * line)42 int LYUpload(char *line)
43 {
44     char *method, *directory;
45     int method_number;
46     int count;
47     char *the_upload = 0;
48     char tmpbuf[LY_MAXPATH];
49     char *filename = NULL;
50     lynx_list_item_type *upload_command = 0;
51     char *the_command = 0;
52 
53     /*
54      * Use configured upload commands.
55      */
56     if ((directory = LYstrstr(line, "TO=")) == NULL)
57 	goto failed;
58     *(directory - 1) = '\0';
59     /* go past "TO=" */
60     directory += 3;
61 
62     if ((method = LYstrstr(line, "UPLOAD=")) == NULL)
63 	goto failed;
64     /*
65      * Go past "UPLOAD=".
66      */
67     method += 7;
68     method_number = atoi(method);
69 
70     for (count = 0, upload_command = uploaders; count < method_number;
71 	 count++, upload_command = upload_command->next) ;	/* null body */
72 
73     /*
74      * Parsed out the Method and the Location?
75      */
76     if (upload_command->command == NULL) {
77 	HTAlert(gettext("ERROR! - upload command is misconfigured"));
78 	goto failed;
79     }
80 
81     /*
82      * Care about the local name?
83      */
84     if (HTCountCommandArgs(upload_command->command)) {
85 	/*
86 	 * Commands have the form "command %s [etc]" where %s is the filename.
87 	 */
88 	_statusline(FILENAME_PROMPT);
89       retry:
90 	*tmpbuf = '\0';
91 	if (LYGetStr(tmpbuf, FALSE, sizeof(tmpbuf), NORECALL) < 0)
92 	    goto cancelled;
93 
94 	if (*tmpbuf == '\0')
95 	    goto cancelled;
96 
97 	if (strstr(tmpbuf, "../") != NULL) {
98 	    HTAlert(gettext("Illegal redirection \"../\" found! Request ignored."));
99 	    goto cancelled;
100 	} else if (StrChr(tmpbuf, '/') != NULL) {
101 	    HTAlert(gettext("Illegal character \"/\" found! Request ignored."));
102 	    goto cancelled;
103 	} else if (tmpbuf[0] == '~') {
104 	    HTAlert(gettext("Illegal redirection using \"~\" found! Request ignored."));
105 	    goto cancelled;
106 	}
107 	HTSprintf0(&filename, "%s/%s", directory, tmpbuf);
108 
109 #ifdef HAVE_POPEN
110 	if (LYIsPipeCommand(filename)) {
111 	    HTAlert(CANNOT_WRITE_TO_FILE);
112 	    _statusline(NEW_FILENAME_PROMPT);
113 	    goto retry;
114 	}
115 #endif
116 	switch (LYValidateOutput(filename)) {
117 	case 'Y':
118 	    break;
119 	case 'N':
120 	    goto retry;
121 	default:
122 	    goto cancelled;
123 	}
124 
125 	/*
126 	 * See if we can write to it.
127 	 */
128 	CTRACE((tfp, "LYUpload: filename is %s", filename));
129 
130 	HTAddParam(&the_upload, upload_command->command, 1, filename);
131 	HTEndParam(&the_upload, upload_command->command, 1);
132     } else {			/* No substitution, no changes */
133 	StrAllocCopy(the_upload, upload_command->command);
134     }
135 
136     HTAddParam(&the_command, SUBDIR_COMMAND, 1, directory);
137     HTEndParam(&the_command, SUBDIR_COMMAND, 1);
138     StrAllocCat(the_command, the_upload);
139 
140     CTRACE((tfp, "command: %s\n", the_command));
141 
142     stop_curses();
143     LYSystem(the_command);
144     start_curses();
145 
146     FREE(the_command);
147     FREE(the_upload);
148 #if defined(MULTI_USER_UNIX)
149     if (filename != 0)
150 	chmod(filename, HIDE_CHMOD);
151 #endif /* UNIX */
152     FREE(filename);
153 
154     return 1;
155 
156   failed:
157     HTAlert(gettext("Unable to upload file."));
158     return 0;
159 
160   cancelled:
161     HTInfoMsg(CANCELLING);
162     return 0;
163 }
164 
165 /*
166  * LYUpload_options writes out the current upload choices to a file so that the
167  * user can select printers in the same way that they select all other links.
168  * Upload links look like:
169  *	LYNXDIRED://UPLOAD=<#>/TO=<STRING>
170  */
LYUpload_options(char ** newfile,char * directory)171 int LYUpload_options(char **newfile,
172 		     char *directory)
173 {
174     static char tempfile[LY_MAXPATH];
175     FILE *fp0;
176     lynx_list_item_type *cur_upload;
177     int count;
178     char *curloc = NULL;
179 
180     if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
181 	return (-1);
182 
183 #ifdef VMS
184     StrAllocCopy(curloc, "/sys$login");
185 #else
186     StrAllocCopy(curloc, HTfullURL_toFile(directory));
187     LYTrimPathSep(curloc);
188 #endif /* VMS */
189 
190     LYLocalFileToURL(newfile, tempfile);
191     LYRegisterUIPage(*newfile, UIP_UPLOAD_OPTIONS);
192 
193     BeginInternalPage(fp0, UPLOAD_OPTIONS_TITLE, UPLOAD_OPTIONS_HELP);
194 
195     fprintf(fp0, "<pre>\n");
196     fprintf(fp0, "   <em>%s</em> %s\n", gettext("Upload To:"), curloc);
197     fprintf(fp0, "\n%s\n", gettext("Upload options:"));
198 
199     if (uploaders != NULL) {
200 	for (count = 0, cur_upload = uploaders;
201 	     cur_upload != NULL;
202 	     cur_upload = cur_upload->next, count++) {
203 	    fprintf(fp0, "   <a href=\"LYNXDIRED://UPLOAD=%d/TO=%s\">",
204 		    count, curloc);
205 	    fprintf(fp0, "%s", (cur_upload->name ?
206 				cur_upload->name : gettext("No Name Given")));
207 	    fprintf(fp0, "</a>\n");
208 	}
209     } else {
210 	fprintf(fp0, "   &lt;NONE&gt;\n");
211     }
212 
213     fprintf(fp0, "</pre>\n");
214     EndInternalPage(fp0);
215     LYCloseTempFP(fp0);
216 
217     LYforce_no_cache = TRUE;
218     FREE(curloc);
219 
220     return (0);
221 }
222