├── ConfigGuide.txt ├── Makefile ├── Tanda.conf ├── capture ├── cgic.c ├── cgic.h ├── cgictest.c ├── config.c ├── config.cgi ├── config.html ├── index.html ├── login.cgi ├── login ├── cgic.c ├── cgic.h ├── login.c └── login.cgi ├── photos ├── background.jpg ├── checkcode.bmp ├── index-footer-bg.gif ├── index-header-bg.gif ├── index-logo.gif ├── index-logout.png ├── index-menu-bg.gif ├── index-menu-bg2.gif ├── index-menu-title.gif ├── index-menu-title.png ├── index-nav-bg.png ├── index-nav-firstbg.png ├── index-nav-left.png ├── index-nav-right.png ├── index-submenu-bg.gif ├── index-subnav-bg.gif ├── index-subnav-left.gif ├── index-subnav-right.gif ├── login-bg.gif ├── login-bg.png ├── login-btn.gif ├── login-input.gif ├── login.css ├── page-bg.gif ├── page-pageTitle-bg.gif ├── page-thead-bg.gif ├── sidebar-on.gif └── style.css ├── readme.txt ├── waterconfig.c └── watersys.html /ConfigGuide.txt: -------------------------------------------------------------------------------- 1 | /****************************凌福义 2016/08/30**********************************************/ 2 | 3 | 4 | 5 | 请在使用CGI文件前详细读取设置选项 6 | 1:将编译好的config.cgi login.cgi放置在/usr/local/boa/cgi-bin下,且修改其权限为777 7 | 2:将index.html和config.html放置在boa文件夹下 8 | 3:修改/data/Tanda.conf/,/data ,/data/update, /data/uplog,的权限为777,且在uplog文件写入字符5(表示网页和server交互的默认状态) 9 | 10 | 11 | 对于uplog文件的各个状态表示为: 12 | 0:表示系统升级成功 13 | 1:表示MD5校验失败 14 | 2:表示解压状态失败 15 | 3:表示安装失败 16 | 4:表示删除升级文件失败 //后续状态修改需要修改cgi文件和html文件 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | cc=arm-fsl-linux-gnueabi-gcc 2 | 3 | all:config.cgi login.cgi 4 | 5 | config.cgi:config.c cgic.c cgic.h 6 | $(cc) -o config.cgi cgic.c config.c 7 | 8 | login.cgi:login/login.c 9 | $(cc) -o login.cgi login/login.c 10 | 11 | waterconfig.cgi:waterconfig.c cgic.c cgic.h 12 | $(cc) -lsqlite3 -o waterconfig.cgi waterconfig.c cgic.c 13 | clean: 14 | rm -rf *.cgi 15 | -------------------------------------------------------------------------------- /Tanda.conf: -------------------------------------------------------------------------------- 1 | ################################### 2 | # Tanda Adapter Config File # 3 | ################################### 4 | 5 | #HardVersion 6 | HardVersion=v1.03 7 | 8 | 9 | #SoftVersion 10 | SoftVersion=v1.11 11 | 12 | #SysType 13 | SysType=01 14 | 15 | 16 | #IMEI 17 | IMEI=00F23E012 18 | 19 | 20 | Service IP 21 | ip=www.jzxfyun.com 22 | 23 | #Service Port 24 | port=5000 25 | 26 | #1 is 232 , 2 is 485 , 3 is all 27 | portenable=1 28 | 29 | #Baudrate 30 | baudrate232=9600 31 | 32 | 33 | #protocolName232 34 | protocolName232=./Tanda3016_232.so 35 | 36 | 37 | #Baudrate485 38 | baudrate485=9600 39 | 40 | #protocolName 41 | protocolName485=./Tanda3016_485.so 42 | 43 | 44 | -------------------------------------------------------------------------------- /capture: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/capture -------------------------------------------------------------------------------- /cgic.h: -------------------------------------------------------------------------------- 1 | /* The CGI_C library, by Thomas Boutell, version 2.01. CGI_C is intended 2 | to be a high-quality API to simplify CGI programming tasks. */ 3 | 4 | /* Make sure this is only included once. */ 5 | 6 | #ifndef CGI_C 7 | #define CGI_C 1 8 | 9 | /* Bring in standard I/O since some of the functions refer to 10 | types defined by it, such as FILE *. */ 11 | 12 | #include 13 | 14 | /* The various CGI environment variables. Instead of using getenv(), 15 | the programmer should refer to these, which are always 16 | valid null-terminated strings (they may be empty, but they 17 | will never be null). If these variables are used instead 18 | of calling getenv(), then it will be possible to save 19 | and restore CGI environments, which is highly convenient 20 | for debugging. */ 21 | 22 | extern char *cgiServerSoftware; 23 | extern char *cgiServerName; 24 | extern char *cgiGatewayInterface; 25 | extern char *cgiServerProtocol; 26 | extern char *cgiServerPort; 27 | extern char *cgiRequestMethod; 28 | extern char *cgiPathInfo; 29 | extern char *cgiPathTranslated; 30 | extern char *cgiScriptName; 31 | extern char *cgiQueryString; 32 | extern char *cgiRemoteHost; 33 | extern char *cgiRemoteAddr; 34 | extern char *cgiAuthType; 35 | extern char *cgiRemoteUser; 36 | extern char *cgiRemoteIdent; 37 | extern char *cgiContentType; 38 | extern char *cgiAccept; 39 | extern char *cgiUserAgent; 40 | extern char *cgiReferrer; 41 | 42 | /* Cookies as sent to the server. You can also get them 43 | individually, or as a string array; see the documentation. */ 44 | extern char *cgiCookie; 45 | 46 | /* A macro providing the same incorrect spelling that is 47 | found in the HTTP/CGI specifications */ 48 | #define cgiReferer cgiReferrer 49 | 50 | /* The number of bytes of data received. 51 | Note that if the submission is a form submission 52 | the library will read and parse all the information 53 | directly from cgiIn; the programmer need not do so. */ 54 | 55 | extern int cgiContentLength; 56 | 57 | /* Pointer to CGI output. The cgiHeader functions should be used 58 | first to output the mime headers; the output HTML 59 | page, GIF image or other web document should then be written 60 | to cgiOut by the programmer. In the standard CGIC library, 61 | cgiOut is always equivalent to stdout. */ 62 | 63 | extern FILE *cgiOut; 64 | 65 | /* Pointer to CGI input. The programmer does not read from this. 66 | We have continued to export it for backwards compatibility 67 | so that cgic 1.x applications link properly. */ 68 | 69 | extern FILE *cgiIn; 70 | 71 | /* Possible return codes from the cgiForm family of functions (see below). */ 72 | 73 | typedef enum { 74 | cgiFormSuccess, 75 | cgiFormTruncated, 76 | cgiFormBadType, 77 | cgiFormEmpty, 78 | cgiFormNotFound, 79 | cgiFormConstrained, 80 | cgiFormNoSuchChoice, 81 | cgiFormMemory, 82 | cgiFormNoFileName, 83 | cgiFormNoContentType, 84 | cgiFormNotAFile, 85 | cgiFormOpenFailed, 86 | cgiFormIO, 87 | cgiFormEOF 88 | } cgiFormResultType; 89 | 90 | /* These functions are used to retrieve form data. See 91 | cgic.html for documentation. */ 92 | 93 | extern cgiFormResultType cgiFormString( 94 | char *name, char *result, int max); 95 | 96 | extern cgiFormResultType cgiFormStringNoNewlines( 97 | char *name, char *result, int max); 98 | 99 | 100 | extern cgiFormResultType cgiFormStringSpaceNeeded( 101 | char *name, int *length); 102 | 103 | 104 | extern cgiFormResultType cgiFormStringMultiple( 105 | char *name, char ***ptrToStringArray); 106 | 107 | extern void cgiStringArrayFree(char **stringArray); 108 | 109 | extern cgiFormResultType cgiFormInteger( 110 | char *name, int *result, int defaultV); 111 | 112 | extern cgiFormResultType cgiFormIntegerBounded( 113 | char *name, int *result, int min, int max, int defaultV); 114 | 115 | extern cgiFormResultType cgiFormDouble( 116 | char *name, double *result, double defaultV); 117 | 118 | extern cgiFormResultType cgiFormDoubleBounded( 119 | char *name, double *result, double min, double max, double defaultV); 120 | 121 | extern cgiFormResultType cgiFormSelectSingle( 122 | char *name, char choicesText[][40], int choicesTotal, 123 | int *result, int defaultV); 124 | 125 | 126 | extern cgiFormResultType cgiFormSelectMultiple( 127 | char *name, char **choicesText, int choicesTotal, 128 | int *result, int *invalid); 129 | 130 | /* Just an alias; users have asked for this */ 131 | #define cgiFormSubmitClicked cgiFormCheckboxSingle 132 | 133 | extern cgiFormResultType cgiFormCheckboxSingle( 134 | char *name); 135 | 136 | extern cgiFormResultType cgiFormCheckboxMultiple( 137 | char *name, char **valuesText, int valuesTotal, 138 | int *result, int *invalid); 139 | 140 | extern cgiFormResultType cgiFormRadio( 141 | char *name, char **valuesText, int valuesTotal, 142 | int *result, int defaultV); 143 | 144 | /* The paths returned by this function are the original names of files 145 | as reported by the uploading web browser and shoult NOT be 146 | blindly assumed to be "safe" names for server-side use! */ 147 | extern cgiFormResultType cgiFormFileName( 148 | char *name, char *result, int max); 149 | 150 | /* The content type of the uploaded file, as reported by the browser. 151 | It should NOT be assumed that browsers will never falsify 152 | such information. */ 153 | extern cgiFormResultType cgiFormFileContentType( 154 | char *name, char *result, int max); 155 | 156 | extern cgiFormResultType cgiFormFileSize( 157 | char *name, int *sizeP); 158 | 159 | typedef struct cgiFileStruct *cgiFilePtr; 160 | 161 | extern cgiFormResultType cgiFormFileOpen( 162 | char *name, cgiFilePtr *cfpp); 163 | 164 | extern cgiFormResultType cgiFormFileRead( 165 | cgiFilePtr cfp, char *buffer, int bufferSize, int *gotP); 166 | 167 | extern cgiFormResultType cgiFormFileClose( 168 | cgiFilePtr cfp); 169 | 170 | extern cgiFormResultType cgiCookieString( 171 | char *name, char *result, int max); 172 | 173 | extern cgiFormResultType cgiCookieInteger( 174 | char *name, int *result, int defaultV); 175 | 176 | cgiFormResultType cgiCookies( 177 | char ***ptrToStringArray); 178 | 179 | /* path can be null or empty in which case a path of / (entire site) is set. 180 | domain can be a single web site; if it is an entire domain, such as 181 | 'boutell.com', it should begin with a dot: '.boutell.com' */ 182 | extern void cgiHeaderCookieSetString(char *name, char *value, 183 | int secondsToLive, char *path, char *domain); 184 | extern void cgiHeaderCookieSetInteger(char *name, int value, 185 | int secondsToLive, char *path, char *domain); 186 | extern void cgiHeaderLocation(char *redirectUrl); 187 | extern void cgiHeaderStatus(int status, char *statusMessage); 188 | extern void cgiHeaderContentType(char *mimeType); 189 | 190 | typedef enum { 191 | cgiEnvironmentIO, 192 | cgiEnvironmentMemory, 193 | cgiEnvironmentSuccess, 194 | cgiEnvironmentWrongVersion 195 | } cgiEnvironmentResultType; 196 | 197 | extern cgiEnvironmentResultType cgiWriteEnvironment(char *filename); 198 | extern cgiEnvironmentResultType cgiReadEnvironment(char *filename); 199 | 200 | extern int cgiMain(); 201 | 202 | extern cgiFormResultType cgiFormEntries( 203 | char ***ptrToStringArray); 204 | 205 | /* Output string with the <, &, and > characters HTML-escaped. 206 | 's' is null-terminated. Returns cgiFormIO in the event 207 | of error, cgiFormSuccess otherwise. */ 208 | cgiFormResultType cgiHtmlEscape(const char *s); 209 | 210 | /* Output data with the <, &, and > characters HTML-escaped. 211 | 'data' is not null-terminated; 'len' is the number of 212 | bytes in 'data'. Returns cgiFormIO in the event 213 | of error, cgiFormSuccess otherwise. */ 214 | cgiFormResultType cgiHtmlEscapeData(const char *data, int len); 215 | 216 | /* Output string with the " character HTML-escaped, and no 217 | other characters escaped. This is useful when outputting 218 | the contents of a tag attribute such as 'href' or 'src'. 219 | 's' is null-terminated. Returns cgiFormIO in the event 220 | of error, cgiFormSuccess otherwise. */ 221 | cgiFormResultType cgiValueEscape(const char *s); 222 | 223 | /* Output data with the " character HTML-escaped, and no 224 | other characters escaped. This is useful when outputting 225 | the contents of a tag attribute such as 'href' or 'src'. 226 | 'data' is not null-terminated; 'len' is the number of 227 | bytes in 'data'. Returns cgiFormIO in the event 228 | of error, cgiFormSuccess otherwise. */ 229 | cgiFormResultType cgiValueEscapeData(const char *data, int len); 230 | 231 | 232 | #endif /* CGI_C */ 233 | 234 | -------------------------------------------------------------------------------- /cgictest.c: -------------------------------------------------------------------------------- 1 | /* Change this if the SERVER_NAME environment variable does not report 2 | the true name of your web server. */ 3 | #if 1 4 | #define SERVER_NAME cgiServerName 5 | #endif 6 | #if 0 7 | #define SERVER_NAME "www.boutell.com" 8 | #endif 9 | 10 | /* You may need to change this, particularly under Windows; 11 | it is a reasonable guess as to an acceptable place to 12 | store a saved environment in order to test that feature. 13 | If that feature is not important to you, you needn't 14 | concern yourself with this. */ 15 | 16 | #ifdef WIN32 17 | #define SAVED_ENVIRONMENT "c:\\cgicsave.env" 18 | #else 19 | #define SAVED_ENVIRONMENT "/tmp/cgicsave.env" 20 | #endif /* WIN32 */ 21 | 22 | #include 23 | #include "cgic.h" 24 | #include 25 | #include 26 | 27 | void HandleSubmit(); 28 | void ShowForm(); 29 | void CookieSet(); 30 | void Name(); 31 | void Address(); 32 | void Hungry(); 33 | void Temperature(); 34 | void Frogs(); 35 | void Color(); 36 | void Flavors(); 37 | void NonExButtons(); 38 | void RadioButtons(); 39 | void File(); 40 | void Entries(); 41 | void Cookies(); 42 | void LoadEnvironment(); 43 | void SaveEnvironment(); 44 | 45 | int cgiMain() { 46 | #ifdef DEBUG 47 | LoadEnvironment(); 48 | #endif /* DEBUG */ 49 | /* Load a previously saved CGI scenario if that button 50 | has been pressed. */ 51 | if (cgiFormSubmitClicked("loadenvironment") == cgiFormSuccess) { 52 | LoadEnvironment(); 53 | } 54 | /* Set any new cookie requested. Must be done *before* 55 | outputting the content type. */ 56 | CookieSet(); 57 | /* Send the content type, letting the browser know this is HTML */ 58 | cgiHeaderContentType("text/html"); 59 | /* Top of the page */ 60 | fprintf(cgiOut, "\n"); 61 | fprintf(cgiOut, "cgic test\n"); 62 | fprintf(cgiOut, "

cgic test

\n"); 63 | /* If a submit button has already been clicked, act on the 64 | submission of the form. */ 65 | if ((cgiFormSubmitClicked("testcgic") == cgiFormSuccess) || 66 | cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) 67 | { 68 | HandleSubmit(); 69 | fprintf(cgiOut, "
\n"); 70 | } 71 | /* Now show the form */ 72 | ShowForm(); 73 | /* Finish up the page */ 74 | fprintf(cgiOut, "\n"); 75 | return 0; 76 | } 77 | 78 | void HandleSubmit() 79 | { 80 | Name(); 81 | Address(); 82 | Hungry(); 83 | Temperature(); 84 | Frogs(); 85 | Color(); 86 | Flavors(); 87 | NonExButtons(); 88 | RadioButtons(); 89 | File(); 90 | Entries(); 91 | Cookies(); 92 | /* The saveenvironment button, in addition to submitting the form, 93 | also saves the resulting CGI scenario to disk for later 94 | replay with the 'load saved environment' button. */ 95 | if (cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) { 96 | SaveEnvironment(); 97 | } 98 | } 99 | 100 | void Name() { 101 | char name[81]; 102 | cgiFormStringNoNewlines("name", name, 81); 103 | fprintf(cgiOut, "Name: "); 104 | cgiHtmlEscape(name); 105 | fprintf(cgiOut, "
\n"); 106 | } 107 | 108 | void Address() { 109 | char address[241]; 110 | cgiFormString("address", address, 241); 111 | fprintf(cgiOut, "Address:
\n");
112 | 	cgiHtmlEscape(address);
113 | 	fprintf(cgiOut, "
\n"); 114 | } 115 | 116 | void Hungry() { 117 | if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) { 118 | fprintf(cgiOut, "I'm Hungry!
\n"); 119 | } else { 120 | fprintf(cgiOut, "I'm Not Hungry!
\n"); 121 | } 122 | } 123 | 124 | void Temperature() { 125 | double temperature; 126 | cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6); 127 | fprintf(cgiOut, "My temperature is %f.
\n", temperature); 128 | } 129 | 130 | void Frogs() { 131 | int frogsEaten; 132 | cgiFormInteger("frogs", &frogsEaten, 0); 133 | fprintf(cgiOut, "I have eaten %d frogs.
\n", frogsEaten); 134 | } 135 | 136 | char *colors[] = { 137 | "Red", 138 | "Green", 139 | "Blue" 140 | }; 141 | 142 | void Color() { 143 | int colorChoice; 144 | cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0); 145 | fprintf(cgiOut, "I am: %s
\n", colors[colorChoice]); 146 | } 147 | 148 | char *flavors[] = { 149 | "pistachio", 150 | "walnut", 151 | "creme" 152 | }; 153 | 154 | void Flavors() { 155 | int flavorChoices[3]; 156 | int i; 157 | int result; 158 | int invalid; 159 | result = cgiFormSelectMultiple("flavors", flavors, 3, 160 | flavorChoices, &invalid); 161 | if (result == cgiFormNotFound) { 162 | fprintf(cgiOut, "I hate ice cream.

\n"); 163 | } else { 164 | fprintf(cgiOut, "My favorite ice cream flavors are:\n"); 165 | fprintf(cgiOut, "

    \n"); 166 | for (i=0; (i < 3); i++) { 167 | if (flavorChoices[i]) { 168 | fprintf(cgiOut, "
  • %s\n", flavors[i]); 169 | } 170 | } 171 | fprintf(cgiOut, "
\n"); 172 | } 173 | } 174 | 175 | char *ages[] = { 176 | "1", 177 | "2", 178 | "3", 179 | "4" 180 | }; 181 | 182 | void RadioButtons() { 183 | int ageChoice; 184 | char ageText[10]; 185 | /* Approach #1: check for one of several valid responses. 186 | Good if there are a short list of possible button values and 187 | you wish to enumerate them. */ 188 | cgiFormRadio("age", ages, 4, &ageChoice, 0); 189 | 190 | fprintf(cgiOut, "Age of Truck: %s (method #1)
\n", 191 | ages[ageChoice]); 192 | 193 | /* Approach #2: just get the string. Good 194 | if the information is not critical or if you wish 195 | to verify it in some other way. Note that if 196 | the information is numeric, cgiFormInteger, 197 | cgiFormDouble, and related functions may be 198 | used instead of cgiFormString. */ 199 | cgiFormString("age", ageText, 10); 200 | 201 | fprintf(cgiOut, "Age of Truck: %s (method #2)
\n", ageText); 202 | } 203 | 204 | char *votes[] = { 205 | "A", 206 | "B", 207 | "C", 208 | "D" 209 | }; 210 | 211 | void NonExButtons() { 212 | int voteChoices[4]; 213 | int i; 214 | int result; 215 | int invalid; 216 | 217 | char **responses; 218 | 219 | /* Method #1: check for valid votes. This is a good idea, 220 | since votes for nonexistent candidates should probably 221 | be discounted... */ 222 | fprintf(cgiOut, "Votes (method 1):
\n"); 223 | result = cgiFormCheckboxMultiple("vote", votes, 4, 224 | voteChoices, &invalid); 225 | if (result == cgiFormNotFound) { 226 | fprintf(cgiOut, "I hate them all!

\n"); 227 | } else { 228 | fprintf(cgiOut, "My preferred candidates are:\n"); 229 | fprintf(cgiOut, "

    \n"); 230 | for (i=0; (i < 4); i++) { 231 | if (voteChoices[i]) { 232 | fprintf(cgiOut, "
  • %s\n", votes[i]); 233 | } 234 | } 235 | fprintf(cgiOut, "
\n"); 236 | } 237 | 238 | /* Method #2: get all the names voted for and trust them. 239 | This is good if the form will change more often 240 | than the code and invented responses are not a danger 241 | or can be checked in some other way. */ 242 | fprintf(cgiOut, "Votes (method 2):
\n"); 243 | result = cgiFormStringMultiple("vote", &responses); 244 | if (result == cgiFormNotFound) { 245 | fprintf(cgiOut, "I hate them all!

\n"); 246 | } else { 247 | int i = 0; 248 | fprintf(cgiOut, "My preferred candidates are:\n"); 249 | fprintf(cgiOut, "

    \n"); 250 | while (responses[i]) { 251 | fprintf(cgiOut, "
  • %s\n", responses[i]); 252 | i++; 253 | } 254 | fprintf(cgiOut, "
\n"); 255 | } 256 | /* We must be sure to free the string array or a memory 257 | leak will occur. Simply calling free() would free 258 | the array but not the individual strings. The 259 | function cgiStringArrayFree() does the job completely. */ 260 | cgiStringArrayFree(responses); 261 | } 262 | 263 | void Entries() 264 | { 265 | char **array, **arrayStep; 266 | fprintf(cgiOut, "List of All Submitted Form Field Names:

\n"); 267 | if (cgiFormEntries(&array) != cgiFormSuccess) { 268 | return; 269 | } 270 | arrayStep = array; 271 | fprintf(cgiOut, "

    \n"); 272 | while (*arrayStep) { 273 | fprintf(cgiOut, "
  • "); 274 | cgiHtmlEscape(*arrayStep); 275 | fprintf(cgiOut, "\n"); 276 | arrayStep++; 277 | } 278 | fprintf(cgiOut, "
\n"); 279 | cgiStringArrayFree(array); 280 | } 281 | 282 | void Cookies() 283 | { 284 | char **array, **arrayStep; 285 | char cname[1024], cvalue[1024]; 286 | fprintf(cgiOut, "Cookies Submitted On This Call, With Values (Many Browsers NEVER Submit Cookies):

\n"); 287 | if (cgiCookies(&array) != cgiFormSuccess) { 288 | return; 289 | } 290 | arrayStep = array; 291 | fprintf(cgiOut, "\n"); 292 | fprintf(cgiOut, "\n"); 293 | while (*arrayStep) { 294 | char value[1024]; 295 | fprintf(cgiOut, ""); 296 | fprintf(cgiOut, "
CookieValue
"); 297 | cgiHtmlEscape(*arrayStep); 298 | fprintf(cgiOut, ""); 299 | cgiCookieString(*arrayStep, value, sizeof(value)); 300 | cgiHtmlEscape(value); 301 | fprintf(cgiOut, "\n"); 302 | arrayStep++; 303 | } 304 | fprintf(cgiOut, "
\n"); 305 | cgiFormString("cname", cname, sizeof(cname)); 306 | cgiFormString("cvalue", cvalue, sizeof(cvalue)); 307 | if (strlen(cname)) { 308 | fprintf(cgiOut, "New Cookie Set On This Call:

\n"); 309 | fprintf(cgiOut, "Name: "); 310 | cgiHtmlEscape(cname); 311 | fprintf(cgiOut, "Value: "); 312 | cgiHtmlEscape(cvalue); 313 | fprintf(cgiOut, "

\n"); 314 | fprintf(cgiOut, "If your browser accepts cookies (many do not), this new cookie should appear in the above list the next time the form is submitted.

\n"); 315 | } 316 | cgiStringArrayFree(array); 317 | } 318 | 319 | void File() 320 | { 321 | cgiFilePtr file; 322 | char name[1024]; 323 | char contentType[1024]; 324 | char buffer[1024]; 325 | int size; 326 | int got; 327 | if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess) { 328 | printf("

No file was uploaded.

\n"); 329 | return; 330 | } 331 | fprintf(cgiOut, "The filename submitted was: "); 332 | cgiHtmlEscape(name); 333 | fprintf(cgiOut, "

\n"); 334 | cgiFormFileSize("file", &size); 335 | fprintf(cgiOut, "The file size was: %d bytes

\n", size); 336 | cgiFormFileContentType("file", contentType, sizeof(contentType)); 337 | fprintf(cgiOut, "The alleged content type of the file was: "); 338 | cgiHtmlEscape(contentType); 339 | fprintf(cgiOut, "

\n"); 340 | fprintf(cgiOut, "Of course, this is only the claim the browser made when uploading the file. Much like the filename, it cannot be trusted.

\n"); 341 | fprintf(cgiOut, "The file's contents are shown here:

\n"); 342 | if (cgiFormFileOpen("file", &file) != cgiFormSuccess) { 343 | fprintf(cgiOut, "Could not open the file.

\n"); 344 | return; 345 | } 346 | fprintf(cgiOut, "

\n");
347 | 	while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==
348 | 		cgiFormSuccess)
349 | 	{
350 | 		cgiHtmlEscapeData(buffer, got);
351 | 	}
352 | 	fprintf(cgiOut, "
\n"); 353 | cgiFormFileClose(file); 354 | } 355 | 356 | void ShowForm() 357 | { 358 | fprintf(cgiOut, ""); 359 | fprintf(cgiOut, "
\n"); 363 | fprintf(cgiOut, "

\n"); 364 | fprintf(cgiOut, "Text Field containing Plaintext\n"); 365 | fprintf(cgiOut, "

\n"); 366 | fprintf(cgiOut, "Your Name\n"); 367 | fprintf(cgiOut, "

\n"); 368 | fprintf(cgiOut, "Multiple-Line Text Field\n"); 369 | fprintf(cgiOut, "

\n"); 370 | fprintf(cgiOut, "\n"); 373 | fprintf(cgiOut, "

\n"); 374 | fprintf(cgiOut, "Checkbox\n"); 375 | fprintf(cgiOut, "

\n"); 376 | fprintf(cgiOut, "Hungry\n"); 377 | fprintf(cgiOut, "

\n"); 378 | fprintf(cgiOut, "Text Field containing a Numeric Value\n"); 379 | fprintf(cgiOut, "

\n"); 380 | fprintf(cgiOut, "\n"); 381 | fprintf(cgiOut, "Blood Temperature (80.0-120.0)\n"); 382 | fprintf(cgiOut, "

\n"); 383 | fprintf(cgiOut, "Text Field containing an Integer Value\n"); 384 | fprintf(cgiOut, "

\n"); 385 | fprintf(cgiOut, "\n"); 386 | fprintf(cgiOut, "Frogs Eaten\n"); 387 | fprintf(cgiOut, "

\n"); 388 | fprintf(cgiOut, "Single-SELECT\n"); 389 | fprintf(cgiOut, "
\n"); 390 | fprintf(cgiOut, "\n"); 395 | fprintf(cgiOut, "
\n"); 396 | fprintf(cgiOut, "Multiple-SELECT\n"); 397 | fprintf(cgiOut, "
\n"); 398 | fprintf(cgiOut, "\n"); 403 | fprintf(cgiOut, "

Exclusive Radio Button Group: Age of Truck in Years\n"); 404 | fprintf(cgiOut, "1\n"); 405 | fprintf(cgiOut, "2\n"); 406 | fprintf(cgiOut, "3\n"); 407 | fprintf(cgiOut, "4\n"); 408 | fprintf(cgiOut, "

Nonexclusive Checkbox Group: Voting for Zero through Four Candidates\n"); 409 | fprintf(cgiOut, "A\n"); 410 | fprintf(cgiOut, "B\n"); 411 | fprintf(cgiOut, "C\n"); 412 | fprintf(cgiOut, "D\n"); 413 | fprintf(cgiOut, "

File Upload:\n"); 414 | fprintf(cgiOut, " (Select A Local File)\n"); 415 | fprintf(cgiOut, "

\n"); 416 | fprintf(cgiOut, "

Set a Cookie

\n"); 417 | fprintf(cgiOut, " Cookie Name\n"); 418 | fprintf(cgiOut, " Cookie Value

\n"); 419 | fprintf(cgiOut, "\n"); 420 | fprintf(cgiOut, "\n"); 421 | fprintf(cgiOut, "

Save the CGI Environment

\n"); 422 | fprintf(cgiOut, "Pressing this button will submit the form, then save the CGI environment so that it can be replayed later by calling cgiReadEnvironment (in a debugger, for instance).

\n"); 423 | fprintf(cgiOut, "\n"); 424 | fprintf(cgiOut, "

\n"); 425 | } 426 | 427 | void CookieSet() 428 | { 429 | char cname[1024]; 430 | char cvalue[1024]; 431 | /* Must set cookies BEFORE calling cgiHeaderContentType */ 432 | cgiFormString("cname", cname, sizeof(cname)); 433 | cgiFormString("cvalue", cvalue, sizeof(cvalue)); 434 | if (strlen(cname)) { 435 | /* Cookie lives for one day (or until browser chooses 436 | to get rid of it, which may be immediately), 437 | and applies only to this script on this site. */ 438 | cgiHeaderCookieSetString(cname, cvalue, 439 | 86400, cgiScriptName, SERVER_NAME); 440 | } 441 | } 442 | 443 | void LoadEnvironment() 444 | { 445 | if (cgiReadEnvironment(SAVED_ENVIRONMENT) != 446 | cgiEnvironmentSuccess) 447 | { 448 | cgiHeaderContentType("text/html"); 449 | fprintf(cgiOut, "Error\n"); 450 | fprintf(cgiOut, "

Error

\n"); 451 | fprintf(cgiOut, "cgiReadEnvironment failed. Most " 452 | "likely you have not saved an environment " 453 | "yet.\n"); 454 | exit(0); 455 | } 456 | /* OK, return now and show the results of the saved environment */ 457 | } 458 | 459 | void SaveEnvironment() 460 | { 461 | if (cgiWriteEnvironment(SAVED_ENVIRONMENT) != 462 | cgiEnvironmentSuccess) 463 | { 464 | fprintf(cgiOut, "

cgiWriteEnvironment failed. Most " 465 | "likely %s is not a valid path or is not " 466 | "writable by the user that the CGI program " 467 | "is running as.

\n", SAVED_ENVIRONMENT); 468 | } else { 469 | fprintf(cgiOut, "

Environment saved. Click this button " 470 | "to restore it, playing back exactly the same " 471 | "scenario: " 472 | "

" 475 | "

\n"); 478 | } 479 | } 480 | 481 | -------------------------------------------------------------------------------- /config.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cgic.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define SOFILENUM 10 13 | #define SOFILELEN 20 14 | 15 | char Ip[20]={0}; 16 | char Port[20]={0}; 17 | char HardVersion[20]={0}; 18 | char SoftVersion[20]={0}; 19 | char IMEI[20]={0}; 20 | char CPUID[30]={0}; 21 | char ControllerID[30]={0}; 22 | char ControllerType[30]={0}; 23 | char MAC[30]={0}; 24 | char Baudrate232[20]={0}; 25 | char Baudrate485[20]={0}; 26 | char Lib232[30]={0}; 27 | char Lib485[30]={0}; 28 | char PortSelect[30]={0}; 29 | char TotleSoFile[50][40]; 30 | char TotleSoNum=0; 31 | const char *BaudrateTable[] = 32 | { 33 | "2400", 34 | "4800", 35 | "9600", 36 | "14400", 37 | "19200", 38 | "38400", 39 | "57600", 40 | "115200", 41 | "230400", 42 | "460800", 43 | "921600" 44 | }; 45 | const char *ControllerTypeTable[]= 46 | { 47 | "1", 48 | "11", 49 | "22", 50 | "31", 51 | "34" 52 | }; 53 | char *PortSelectTable[]= 54 | { 55 | "1", 56 | "2" 57 | }; 58 | 59 | static void CopyIndexStr(char *dest , char *src) 60 | { 61 | int i=0; 62 | for(i=0 ; i<30 ; i++) 63 | { 64 | if('='!=src[i]) 65 | { 66 | dest[i]=src[i]; 67 | } 68 | else 69 | { 70 | break; 71 | } 72 | } 73 | dest[i]='\0'; 74 | } 75 | /* 76 | Find the '=' pos and get the config dat 77 | */ 78 | static int DatPos(char *dat , int index ) 79 | { 80 | int i=0; 81 | if(index==0)//find the config file 82 | { 83 | while((*dat++)!='=') 84 | { 85 | i++; 86 | } 87 | return i; 88 | } 89 | else //find the *.so file 90 | { 91 | while(*(dat+1)&&*dat) 92 | { 93 | if(*dat=='s'&&*(dat+1)=='o') 94 | { 95 | return 1; 96 | } 97 | dat++; 98 | } 99 | return 0; 100 | } 101 | } 102 | 103 | /*Find How many So file */ 104 | void GetFileOfSo(void) 105 | { 106 | FILE *stream; 107 | FILE *wstream; 108 | char buf[1024]; 109 | memset( buf,0,sizeof(buf)); 110 | stream = popen( " ls /data/*.so", "r" ); 111 | wstream = fopen( "/data/Numberso", "w+"); 112 | system("chmod 777 /data/Numberso"); 113 | fread( buf, sizeof(char), sizeof(buf), stream); 114 | fwrite( buf, 1, sizeof(buf), wstream ); 115 | pclose( stream ); 116 | fclose( wstream ); 117 | } 118 | 119 | 120 | void GetMAC(void) 121 | { 122 | FILE *stream; 123 | stream = popen( "cat /etc/cpuid", "r" ); 124 | fread( CPUID, sizeof(char), sizeof(CPUID), stream); 125 | pclose( stream ); 126 | CPUID[sizeof(CPUID)] = '\0'; 127 | stream = popen( "cat /etc/mac", "r" ); 128 | fread( MAC, sizeof(char), sizeof(MAC), stream); 129 | pclose( stream ); 130 | MAC[sizeof(MAC)] = '\0'; 131 | } 132 | 133 | void GetSoFileList(void) 134 | { 135 | 136 | FILE *fd; 137 | TotleSoNum=0; 138 | char StrLine[1024]; 139 | int i; 140 | if((fd = fopen("/data/Numberso","r")) == NULL) 141 | { 142 | return; 143 | } 144 | while (!feof(fd)) 145 | { 146 | fgets(StrLine,1024,fd); 147 | i=DatPos(StrLine,1); 148 | if(i==1) //find a so file 149 | { 150 | strcpy(TotleSoFile[TotleSoNum++], &StrLine[6]); 151 | } 152 | else 153 | { 154 | break; 155 | } 156 | } 157 | fclose(fd); 158 | } 159 | 160 | /*When open html we should read configfile to fix it*/ 161 | void ReadTandaConf(void) 162 | { 163 | FILE *fd; 164 | char StrLine[200]; 165 | char ptr[30]; 166 | int i=0; 167 | if((fd = fopen("/data/Tanda.conf","r")) == NULL) 168 | { 169 | printf("cant't open file\n"); 170 | fclose(fd); 171 | return; 172 | } 173 | 174 | while (!feof(fd)) 175 | { 176 | fgets(StrLine,200,fd); 177 | if(StrLine[0]=='#'||StrLine[0]==' ') 178 | { 179 | continue; 180 | } 181 | else 182 | { 183 | i=DatPos(StrLine , 0); 184 | memset(ptr , 0 , sizeof(ptr)); 185 | CopyIndexStr(ptr,StrLine); 186 | if(!strcmp(ptr , "HardVersion")) 187 | { 188 | strncpy(HardVersion,&StrLine[i+1],sizeof(HardVersion)); 189 | HardVersion[sizeof(HardVersion)-1]='\0'; 190 | } 191 | else if(!strcmp(ptr , "SoftVersion")) 192 | { 193 | strncpy(SoftVersion,&StrLine[i+1],sizeof(SoftVersion)); 194 | SoftVersion[sizeof(SoftVersion)-1]='\0'; 195 | } 196 | else if(!strcmp(ptr , "ControllerType")) 197 | { 198 | strncpy(ControllerType,&StrLine[i+1],sizeof(ControllerType)); 199 | ControllerType[sizeof(ControllerType)-1]='\0'; 200 | } 201 | else if(!strcmp(ptr , "ControllerID")) 202 | { 203 | strncpy(ControllerID,&StrLine[i+1],sizeof(ControllerID)); 204 | ControllerID[sizeof(ControllerID)-1]='\0'; 205 | } 206 | else if(!strcmp(ptr , "IMEI")) 207 | { 208 | strncpy(IMEI,&StrLine[i+1],sizeof(IMEI)); 209 | IMEI[sizeof(IMEI)-1]='\0'; 210 | } 211 | else if(!strcmp(ptr , "ip")) 212 | { 213 | strncpy(Ip,&StrLine[i+1],sizeof(Ip)); 214 | Ip[sizeof(Ip)-1]='\0'; 215 | } 216 | else if(!strcmp(ptr , "port")) 217 | { 218 | strncpy(Port,&StrLine[i+1],sizeof(Port)); 219 | Port[sizeof(Port)-1]='\0'; 220 | } 221 | else if(!strcmp(ptr , "portenable")) 222 | { 223 | strncpy(PortSelect,&StrLine[i+1],sizeof(PortSelect)); 224 | PortSelect[sizeof(PortSelect)-1]='\0'; 225 | } 226 | else if(!strcmp(ptr , "baudrate232")) 227 | { 228 | strncpy(Baudrate232,&StrLine[i+1],sizeof(Baudrate232)); 229 | Baudrate232[sizeof(Baudrate232)-1]='\0'; 230 | } 231 | else if(!strcmp(ptr , "baudrate485")) 232 | { 233 | strncpy(Baudrate485,&StrLine[i+1],sizeof(Baudrate485)); 234 | Baudrate485[sizeof(Baudrate485)-1]='\0'; 235 | } 236 | else if(!strcmp(ptr , "protocolName232")) 237 | { 238 | strncpy(Lib232,&StrLine[i+3],sizeof(Lib232)); 239 | Lib232[sizeof(Lib232)-1]='\0'; 240 | } 241 | else if(!strcmp(ptr , "protocolName485")) 242 | { 243 | strncpy(Lib485,&StrLine[i+3],sizeof(Lib485)); 244 | Lib485[sizeof(Lib485)-1]='\0'; 245 | } 246 | else 247 | ; 248 | } 249 | 250 | } 251 | 252 | fclose(fd); 253 | 254 | } 255 | 256 | int WriteConfDat(void) 257 | { 258 | 259 | FILE *fd; 260 | int SoChoice232; 261 | int bauChoice232; 262 | int SoChoice485; 263 | int bauChoice485; 264 | int controllertypechoice; 265 | int portselect[2]; 266 | int i; 267 | int result , invalid; 268 | ReadTandaConf(); 269 | cgiFormSelectSingleNormal("controllertype", ControllerTypeTable, 5, &controllertypechoice, 0); 270 | cgiFormStringNoNewlines("ip", Ip, sizeof(Ip)); 271 | cgiFormStringNoNewlines("port", Port, sizeof(Port)); 272 | cgiFormStringNoNewlines("controllerid", ControllerID, sizeof(ControllerID)); 273 | result = cgiFormCheckboxMultiple("portcheck", PortSelectTable, 2, portselect, &invalid); 274 | if (cgiFormNotFound == result) 275 | { 276 | return -1; 277 | } 278 | else 279 | { 280 | result=0; 281 | for (i=0; i < 2; i++) 282 | { 283 | if (portselect[i]) 284 | { 285 | result+=(i+1); 286 | } 287 | } 288 | } 289 | 290 | GetSoFileList(); 291 | if(1 == result) 292 | { 293 | PortSelect[0]='1'; 294 | cgiFormSelectSingleNormal("bau232", BaudrateTable, 11, &bauChoice232, 0); 295 | cgiFormSelectSingle("net232", TotleSoFile, TotleSoNum, &SoChoice232, 0); 296 | } 297 | else if(2 == result) 298 | { 299 | PortSelect[0]='2'; 300 | cgiFormSelectSingleNormal("bau485", BaudrateTable, 11, &bauChoice485, 0); 301 | cgiFormSelectSingle("net485", TotleSoFile, TotleSoNum, &SoChoice485, 0); 302 | } 303 | else if(3 == result) 304 | { 305 | PortSelect[0]='3'; 306 | cgiFormSelectSingleNormal("bau232", BaudrateTable, 11, &bauChoice232, 0); 307 | cgiFormSelectSingle("net232", TotleSoFile, TotleSoNum, &SoChoice232, 0); 308 | cgiFormSelectSingleNormal("bau485", BaudrateTable, 11, &bauChoice485, 0); 309 | cgiFormSelectSingle("net485", TotleSoFile, TotleSoNum, &SoChoice485, 0); 310 | } 311 | else 312 | { 313 | return -2; 314 | } 315 | system("chmod 777 /data/Tanda.conf"); 316 | fd=fopen("/data/Tanda.conf" ,"w"); 317 | if(fd) 318 | { 319 | fputs("###################################\n",fd); 320 | fputs("# Tanda Adapter Config File #\n",fd); 321 | fputs("###################################\n\n",fd); 322 | 323 | fputs("#HardVersion\nHardVersion=",fd); 324 | fputs(HardVersion, fd); 325 | fputs("\n\n",fd); 326 | 327 | 328 | fputs("#SoftVersion\nSoftVersion=",fd); 329 | fputs(SoftVersion, fd); 330 | fputs("\n\n",fd); 331 | 332 | fputs("#ControllerType\nControllerType=",fd); 333 | fputs(ControllerTypeTable[controllertypechoice], fd); 334 | fputs("\n\n",fd); 335 | 336 | fputs("#ControllerID\nControllerID=",fd); 337 | fputs(ControllerID, fd); 338 | fputs("\n\n",fd); 339 | 340 | fputs("#IMEI\nIMEI=",fd); 341 | fputs(IMEI, fd); 342 | fputs("\n\n",fd); 343 | 344 | fputs("Service IP\nip=",fd); 345 | fputs(Ip , fd); 346 | fputs("\n\n",fd); 347 | 348 | fputs("#Service Port\nport=",fd); 349 | fputs(Port , fd); 350 | fputs("\n\n",fd); 351 | 352 | fputs("#1 is 232 , 2 is 485 , 3 is all\nportenable=",fd); 353 | fputc(PortSelect[0], fd); 354 | fputs("\n\n",fd); 355 | if(1==result) 356 | { 357 | fputs("#Baudrate\nbaudrate232=",fd); 358 | fputs(BaudrateTable[bauChoice232], fd); 359 | fputs("\n\n",fd); 360 | fputs("#protocolName232\nprotocolName232=./",fd); 361 | fputs(TotleSoFile[SoChoice232] , fd); 362 | fputs("\n\n",fd); 363 | fputs("#Baudrate485\nbaudrate485=",fd); 364 | fputs(Baudrate485, fd); 365 | fputs("\n\n",fd); 366 | fputs("#protocolName\nprotocolName485=./",fd); 367 | fputs(Lib485, fd); 368 | fputs("\n\n",fd); 369 | } 370 | else if (2 == result) 371 | { 372 | fputs("#Baudrate\nbaudrate232=",fd); 373 | fputs(Baudrate232, fd); 374 | fputs("\n\n",fd); 375 | fputs("#protocolName232\nprotocolName232=./",fd); 376 | fputs(Lib232, fd); 377 | fputs("\n\n",fd); 378 | fputs("#Baudrate485\nbaudrate485=",fd); 379 | fputs(BaudrateTable[bauChoice485], fd); 380 | fputs("\n\n",fd); 381 | fputs("#protocolName\nprotocolName485=./",fd); 382 | fputs(TotleSoFile[SoChoice485], fd); 383 | fputs("\n\n",fd); 384 | } 385 | else 386 | { 387 | fputs("#Baudrate\nbaudrate232=",fd); 388 | fputs(BaudrateTable[bauChoice232], fd); 389 | fputs("\n\n",fd); 390 | fputs("#protocolName232\nprotocolName232=./",fd); 391 | fputs(TotleSoFile[SoChoice232], fd); 392 | fputs("\n\n",fd); 393 | fputs("#Baudrate485\nbaudrate485=",fd); 394 | fputs(BaudrateTable[bauChoice485], fd); 395 | fputs("\n\n",fd); 396 | fputs("#protocolName\nprotocolName485=./",fd); 397 | fputs(TotleSoFile[SoChoice485], fd); 398 | fputs("\n\n",fd); 399 | } 400 | fclose(fd); 401 | 402 | } 403 | else 404 | { 405 | printf("err"); 406 | return -3; 407 | } 408 | return 0; 409 | 410 | } 411 | void UpLoadsoFile(void) 412 | { 413 | cgiFilePtr file; 414 | FILE *fd; 415 | char name[1024]; 416 | char path[50]; 417 | char contentType[1024]; 418 | int size; 419 | unsigned int got; 420 | char *tmp = NULL; 421 | if (cgiFormFileName("sofile", name, sizeof(name)) != cgiFormSuccess) { 422 | return ; 423 | } 424 | cgiFormFileSize("sofile", &size); 425 | cgiFormFileContentType("sofile", contentType, sizeof(contentType)); 426 | if (cgiFormFileOpen("sofile", &file) != cgiFormSuccess) { 427 | return ; 428 | } 429 | /*write file */ 430 | 431 | tmp=(char *)malloc(sizeof(char)*size); 432 | strcpy(path , "/data/"); 433 | strcat(path, name); 434 | fd=fopen(path ,"w+"); 435 | if(fd==NULL) 436 | { 437 | return ; 438 | } 439 | while (cgiFormFileRead(file, tmp, size, &got) == 440 | cgiFormSuccess) 441 | { 442 | fwrite(tmp, size, sizeof(char), fd); 443 | } 444 | cgiFormFileClose(file); 445 | free(tmp); 446 | fclose(fd); 447 | return ; 448 | } 449 | 450 | 451 | void UpLoadUpdateFile(void) 452 | { 453 | cgiFilePtr file; 454 | FILE *fd; 455 | char name[1024]; 456 | char path[50]; 457 | char contentType[1024]; 458 | int size; 459 | unsigned int got; 460 | char *tmp = NULL; 461 | if (cgiFormFileName("updatefile", name, sizeof(name)) != cgiFormSuccess) { 462 | return ; 463 | } 464 | cgiFormFileSize("updatefile", &size); 465 | cgiFormFileContentType("updatefile", contentType, sizeof(contentType)); 466 | if (cgiFormFileOpen("updatefile", &file) != cgiFormSuccess) { 467 | return ; 468 | } 469 | /*write file */ 470 | 471 | tmp=(char *)malloc(sizeof(char)*size); 472 | strcpy(path , "/data/update/"); 473 | strcat(path, name); 474 | fd=fopen(path ,"w+"); 475 | if(fd==NULL) 476 | { 477 | return ; 478 | } 479 | while (cgiFormFileRead(file, tmp, size, &got) == 480 | cgiFormSuccess) 481 | { 482 | fwrite(tmp, size, sizeof(char), fd); 483 | } 484 | cgiFormFileClose(file); 485 | free(tmp); 486 | fclose(fd); 487 | return ; 488 | } 489 | 490 | void UpLoadMD5File(void) 491 | { 492 | cgiFilePtr file; 493 | FILE *fd; 494 | char name[1024]; 495 | char path[50]; 496 | char contentType[1024]; 497 | int size; 498 | unsigned int got; 499 | char *tmp = NULL; 500 | if (cgiFormFileName("MD5file", name, sizeof(name)) != cgiFormSuccess) { 501 | return ; 502 | } 503 | //fprintf(cgiOut, "The filename submitted was: "); 504 | //cgiHtmlEscape(name); 505 | //fprintf(cgiOut, "

\n"); 506 | cgiFormFileSize("MD5file", &size); 507 | //fprintf(cgiOut, "The file size was: %d bytes

\n", size); 508 | cgiFormFileContentType("MD5file", contentType, sizeof(contentType)); 509 | //fprintf(cgiOut, "The alleged content type of the file was: "); 510 | //cgiHtmlEscape(contentType); 511 | //fprintf(cgiOut, "

\n"); 512 | 513 | 514 | //fprintf(cgiOut, "Of course, this is only the claim the browser made when uploading the file. Much like the filename, it cannot be trusted.

\n"); 515 | //fprintf(cgiOut, "The file's contents are shown here:

\n"); 516 | if (cgiFormFileOpen("MD5file", &file) != cgiFormSuccess) { 517 | return ; 518 | } 519 | /*write file */ 520 | 521 | tmp=(char *)malloc(sizeof(char)*size); 522 | strcpy(path , "/data/update/"); 523 | strcat(path, name); 524 | fd=fopen(path ,"w+"); 525 | if(fd==NULL) 526 | { 527 | return ; 528 | } 529 | //fprintf(cgiOut, "

\n");
530 | 	while (cgiFormFileRead(file, tmp, size, &got) ==
531 | 		cgiFormSuccess)
532 | 	{
533 | 		fwrite(tmp, size, sizeof(char), fd);
534 | 		//cgiHtmlEscapeData(tmp, size);
535 | 	}
536 | 	//fprintf(cgiOut, "
\n"); 537 | cgiFormFileClose(file); 538 | free(tmp); 539 | fclose(fd); 540 | return ; 541 | } 542 | 543 | void SubmitHandle(void) 544 | { 545 | system("chmod 777 /data"); 546 | system("chmod 777 /data/update"); 547 | UpLoadsoFile(); 548 | UpLoadUpdateFile(); 549 | UpLoadMD5File(); 550 | } 551 | void RequistConfig(void) 552 | { 553 | FILE *fd; 554 | char StrLine[1024]; 555 | int i=0; 556 | GetFileOfSo(); 557 | GetMAC(); 558 | ReadTandaConf(); 559 | fprintf(cgiOut, "SoftVersion=%s/",SoftVersion); 560 | fprintf(cgiOut, "HardVersion=%s/",HardVersion); 561 | fprintf(cgiOut, "MAC=%s/",MAC); 562 | fprintf(cgiOut, "controllertype=%s/",ControllerType); 563 | fprintf(cgiOut, "controllerid=%s/",ControllerID); 564 | fprintf(cgiOut, "CPUID=%s/", CPUID); 565 | fprintf(cgiOut, "IMEI=%s/",IMEI); 566 | fprintf(cgiOut, "Ip=%s/",Ip); 567 | fprintf(cgiOut, "Port=%s/",Port); 568 | if(PortSelect[0]=='1') 569 | { 570 | fprintf(cgiOut, "Portselect=1\n/"); 571 | } 572 | else if(PortSelect[0]=='2') 573 | { 574 | fprintf(cgiOut, "Portselect=2\n/"); 575 | } 576 | else if(PortSelect[0]=='3') 577 | { 578 | fprintf(cgiOut, "Portselect=3\n/"); 579 | } 580 | fprintf(cgiOut, "bau232=%s/",Baudrate232); 581 | fprintf(cgiOut, "Lib232=%s/",Lib232); 582 | fprintf(cgiOut, "bau485=%s/",Baudrate485); 583 | fprintf(cgiOut, "Lib485=%s/",Lib485); 584 | GetSoFileList(); 585 | for(i=0 ; i2) 627 | { 628 | c=GetSysUpState(); 629 | printf("%c=Run",c); 630 | } 631 | else 632 | { 633 | c=GetSysUpState(); 634 | printf("%c=Stop",c); 635 | } 636 | pclose( stream ); 637 | } 638 | int cgiMain() 639 | { 640 | int ret; 641 | char *UserInput = NULL; // index the user input data. 642 | char *request_method = NULL; //index the html transfer type. 643 | int data_len = 0; // index the input data's length. 644 | int lock=0; 645 | printf("Content-type:text/html;charset=utf-8\n\n"); 646 | if( ! getenv("REQUEST_METHOD") ) 647 | { 648 | return -1; 649 | } 650 | request_method = getenv("REQUEST_METHOD"); // trans-type. 651 | // trans-type : GET 652 | if( ! strcmp( request_method, "GET" ) ) 653 | { 654 | if( getenv( "QUERY_STRING" ) ) 655 | { 656 | UserInput = getenv( "QUERY_STRING" ); 657 | } 658 | data_len = strlen( UserInput ); 659 | 660 | if( NULL == UserInput || 0 == data_len ) 661 | { 662 | printf( "There's no input data !\n" ); 663 | return -1; 664 | } 665 | UserInput[data_len] = '\0'; 666 | if(!strncmp(UserInput,"getconf" , 7)) 667 | { 668 | RequistConfig(); 669 | } 670 | else if(!strncmp(UserInput,"getstatus" , 9)) 671 | { 672 | GetSysState(); 673 | } 674 | 675 | } 676 | 677 | if ((cgiFormSubmitClicked("Setting") == cgiFormSuccess)) 678 | { 679 | ret=WriteConfDat(); 680 | if(0==ret) 681 | { 682 | SubmitHandle(); 683 | } 684 | system("echo 6 > /data/uplog"); 685 | } 686 | return 0; 687 | } 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | -------------------------------------------------------------------------------- /config.cgi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/config.cgi -------------------------------------------------------------------------------- /config.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 适配器配置 8 | 110 | 111 | 112 | 113 |
114 | 115 |
116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 129 | 131 | 133 | 139 | 141 | 142 | 143 | 151 | 152 | 153 |
硬件版本号:
软件版本号:
MAC:
适配器ID:
IMEI:
服务器IP:
端口号:
通讯接口选择: 127 | RS232 128 | RS485
波特率(RS232): 130 |
波特率(RS485): 132 |
通讯文件上载:
134 | 135 | 136 |
137 |
通讯协议(RS232): 138 |
通讯协议(RS485): 140 |
控制器类型:
控制器ID:
升级文件上载:
154 | 155 |
156 |
MD5文件上载:
157 |
158 |
159 | 160 |
161 |
162 |
163 |
164 |

165 | 0% 166 |
167 |

168 |
169 | 170 | 171 | 172 | 173 | 174 | 175 | 740 | 741 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | Login 3 | 4 | 5 | 6 | 7 | 8 | 9 |

10 | 11 |
12 |
13 | 14 |
15 |
16 | 17 |
18 |

19 | 20 | 23 |
24 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /login.cgi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/login.cgi -------------------------------------------------------------------------------- /login/cgic.c: -------------------------------------------------------------------------------- 1 | /* cgicTempDir is the only setting you are likely to need 2 | to change in this file. */ 3 | 4 | /* Used only in Unix environments, in conjunction with mkstemp(). 5 | Elsewhere (Windows), temporary files go where the tmpnam() 6 | function suggests. If this behavior does not work for you, 7 | modify the getTempFileName() function to suit your needs. */ 8 | 9 | #define cgicTempDir "/tmp" 10 | 11 | #if CGICDEBUG 12 | #define CGICDEBUGSTART \ 13 | { \ 14 | FILE *dout; \ 15 | dout = fopen("/home/boutell/public_html/debug", "a"); \ 16 | 17 | #define CGICDEBUGEND \ 18 | fclose(dout); \ 19 | } 20 | #else /* CGICDEBUG */ 21 | #define CGICDEBUGSTART 22 | #define CGICDEBUGEND 23 | #endif /* CGICDEBUG */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #ifdef WIN32 34 | #include 35 | 36 | /* cgic 2.01 */ 37 | #include 38 | 39 | #else 40 | #include 41 | #endif /* WIN32 */ 42 | #include "cgic.h" 43 | 44 | #define cgiStrEq(a, b) (!strcmp((a), (b))) 45 | 46 | char *cgiServerSoftware; 47 | char *cgiServerName; 48 | char *cgiGatewayInterface; 49 | char *cgiServerProtocol; 50 | char *cgiServerPort; 51 | char *cgiRequestMethod; 52 | char *cgiPathInfo; 53 | char *cgiPathTranslated; 54 | char *cgiScriptName; 55 | char *cgiQueryString; 56 | char *cgiRemoteHost; 57 | char *cgiRemoteAddr; 58 | char *cgiAuthType; 59 | char *cgiRemoteUser; 60 | char *cgiRemoteIdent; 61 | char cgiContentTypeData[1024]; 62 | char *cgiContentType = cgiContentTypeData; 63 | char *cgiMultipartBoundary; 64 | char *cgiCookie; 65 | int cgiContentLength; 66 | char *cgiAccept; 67 | char *cgiUserAgent; 68 | char *cgiReferrer; 69 | 70 | FILE *cgiIn; 71 | FILE *cgiOut; 72 | 73 | /* True if CGI environment was restored from a file. */ 74 | static int cgiRestored = 0; 75 | 76 | static void cgiGetenv(char **s, char *var); 77 | 78 | typedef enum { 79 | cgiParseSuccess, 80 | cgiParseMemory, 81 | cgiParseIO 82 | } cgiParseResultType; 83 | 84 | /* One form entry, consisting of an attribute-value pair, 85 | and an optional filename and content type. All of 86 | these are guaranteed to be valid null-terminated strings, 87 | which will be of length zero in the event that the 88 | field is not present, with the exception of tfileName 89 | which will be null when 'in' is null. DO NOT MODIFY THESE 90 | VALUES. Make local copies if modifications are desired. */ 91 | 92 | typedef struct cgiFormEntryStruct { 93 | char *attr; 94 | /* value is populated for regular form fields only. 95 | For file uploads, it points to an empty string, and file 96 | upload data should be read from the file tfileName. */ 97 | char *value; 98 | /* When fileName is not an empty string, tfileName is not null, 99 | and 'value' points to an empty string. */ 100 | /* Valid for both files and regular fields; does not include 101 | terminating null of regular fields. */ 102 | int valueLength; 103 | char *fileName; 104 | char *contentType; 105 | /* Temporary file name for working storage of file uploads. */ 106 | char *tfileName; 107 | struct cgiFormEntryStruct *next; 108 | } cgiFormEntry; 109 | 110 | /* The first form entry. */ 111 | static cgiFormEntry *cgiFormEntryFirst; 112 | 113 | static cgiParseResultType cgiParseGetFormInput(); 114 | static cgiParseResultType cgiParsePostFormInput(); 115 | static cgiParseResultType cgiParsePostMultipartInput(); 116 | static cgiParseResultType cgiParseFormInput(char *data, int length); 117 | static void cgiSetupConstants(); 118 | static void cgiFreeResources(); 119 | static int cgiStrEqNc(char *s1, char *s2); 120 | static int cgiStrBeginsNc(char *s1, char *s2); 121 | 122 | #ifdef UNIT_TEST 123 | static int unitTest(); 124 | #endif 125 | 126 | int main(int argc, char *argv[]) { 127 | int result; 128 | char *cgiContentLengthString; 129 | char *e; 130 | cgiSetupConstants(); 131 | cgiGetenv(&cgiServerSoftware, "SERVER_SOFTWARE"); 132 | cgiGetenv(&cgiServerName, "SERVER_NAME"); 133 | cgiGetenv(&cgiGatewayInterface, "GATEWAY_INTERFACE"); 134 | cgiGetenv(&cgiServerProtocol, "SERVER_PROTOCOL"); 135 | cgiGetenv(&cgiServerPort, "SERVER_PORT"); 136 | cgiGetenv(&cgiRequestMethod, "REQUEST_METHOD"); 137 | cgiGetenv(&cgiPathInfo, "PATH_INFO"); 138 | cgiGetenv(&cgiPathTranslated, "PATH_TRANSLATED"); 139 | cgiGetenv(&cgiScriptName, "SCRIPT_NAME"); 140 | cgiGetenv(&cgiQueryString, "QUERY_STRING"); 141 | cgiGetenv(&cgiRemoteHost, "REMOTE_HOST"); 142 | cgiGetenv(&cgiRemoteAddr, "REMOTE_ADDR"); 143 | cgiGetenv(&cgiAuthType, "AUTH_TYPE"); 144 | cgiGetenv(&cgiRemoteUser, "REMOTE_USER"); 145 | cgiGetenv(&cgiRemoteIdent, "REMOTE_IDENT"); 146 | /* 2.0: the content type string needs to be parsed and modified, so 147 | copy it to a buffer. */ 148 | e = getenv("CONTENT_TYPE"); 149 | if (e) { 150 | if (strlen(e) < sizeof(cgiContentTypeData)) { 151 | strcpy(cgiContentType, e); 152 | } else { 153 | /* Truncate safely in the event of what is almost certainly 154 | a hack attempt */ 155 | strncpy(cgiContentType, e, sizeof(cgiContentTypeData)); 156 | cgiContentType[sizeof(cgiContentTypeData) - 1] = '\0'; 157 | } 158 | } else { 159 | cgiContentType[0] = '\0'; 160 | } 161 | /* Never null */ 162 | cgiMultipartBoundary = ""; 163 | /* 2.0: parse semicolon-separated additional parameters of the 164 | content type. The one we're interested in is 'boundary'. 165 | We discard the rest to make cgiContentType more useful 166 | to the typical programmer. */ 167 | if (strchr(cgiContentType, ';')) { 168 | char *sat = strchr(cgiContentType, ';'); 169 | while (sat) { 170 | *sat = '\0'; 171 | sat++; 172 | while (isspace(*sat)) { 173 | sat++; 174 | } 175 | if (cgiStrBeginsNc(sat, "boundary=")) { 176 | char *s; 177 | cgiMultipartBoundary = sat + strlen("boundary="); 178 | s = cgiMultipartBoundary; 179 | while ((*s) && (!isspace(*s))) { 180 | s++; 181 | } 182 | *s = '\0'; 183 | break; 184 | } else { 185 | sat = strchr(sat, ';'); 186 | } 187 | } 188 | } 189 | cgiGetenv(&cgiContentLengthString, "CONTENT_LENGTH"); 190 | cgiContentLength = atoi(cgiContentLengthString); 191 | cgiGetenv(&cgiAccept, "HTTP_ACCEPT"); 192 | cgiGetenv(&cgiUserAgent, "HTTP_USER_AGENT"); 193 | cgiGetenv(&cgiReferrer, "HTTP_REFERER"); 194 | cgiGetenv(&cgiCookie, "HTTP_COOKIE"); 195 | #ifdef CGICDEBUG 196 | CGICDEBUGSTART 197 | fprintf(dout, "%d\n", cgiContentLength); 198 | fprintf(dout, "%s\n", cgiRequestMethod); 199 | fprintf(dout, "%s\n", cgiContentType); 200 | CGICDEBUGEND 201 | #endif /* CGICDEBUG */ 202 | #ifdef WIN32 203 | /* 1.07: Must set stdin and stdout to binary mode */ 204 | /* 2.0: this is particularly crucial now and must not be removed */ 205 | _setmode( _fileno( stdin ), _O_BINARY ); 206 | _setmode( _fileno( stdout ), _O_BINARY ); 207 | #endif /* WIN32 */ 208 | cgiFormEntryFirst = 0; 209 | cgiIn = stdin; 210 | cgiOut = stdout; 211 | cgiRestored = 0; 212 | 213 | 214 | /* These five lines keep compilers from 215 | producing warnings that argc and argv 216 | are unused. They have no actual function. */ 217 | if (argc) { 218 | if (argv[0]) { 219 | cgiRestored = 0; 220 | } 221 | } 222 | 223 | 224 | if (cgiStrEqNc(cgiRequestMethod, "post")) { 225 | #ifdef CGICDEBUG 226 | CGICDEBUGSTART 227 | fprintf(dout, "POST recognized\n"); 228 | CGICDEBUGEND 229 | #endif /* CGICDEBUG */ 230 | if (cgiStrEqNc(cgiContentType, "application/x-www-form-urlencoded")) { 231 | #ifdef CGICDEBUG 232 | CGICDEBUGSTART 233 | fprintf(dout, "Calling PostFormInput\n"); 234 | CGICDEBUGEND 235 | #endif /* CGICDEBUG */ 236 | if (cgiParsePostFormInput() != cgiParseSuccess) { 237 | #ifdef CGICDEBUG 238 | CGICDEBUGSTART 239 | fprintf(dout, "PostFormInput failed\n"); 240 | CGICDEBUGEND 241 | #endif /* CGICDEBUG */ 242 | cgiHeaderStatus(500, "Error reading form data"); 243 | cgiFreeResources(); 244 | return -1; 245 | } 246 | #ifdef CGICDEBUG 247 | CGICDEBUGSTART 248 | fprintf(dout, "PostFormInput succeeded\n"); 249 | CGICDEBUGEND 250 | #endif /* CGICDEBUG */ 251 | } else if (cgiStrEqNc(cgiContentType, "multipart/form-data")) { 252 | #ifdef CGICDEBUG 253 | CGICDEBUGSTART 254 | fprintf(dout, "Calling PostMultipartInput\n"); 255 | CGICDEBUGEND 256 | #endif /* CGICDEBUG */ 257 | if (cgiParsePostMultipartInput() != cgiParseSuccess) { 258 | #ifdef CGICDEBUG 259 | CGICDEBUGSTART 260 | fprintf(dout, "PostMultipartInput failed\n"); 261 | CGICDEBUGEND 262 | #endif /* CGICDEBUG */ 263 | cgiHeaderStatus(500, "Error reading form data"); 264 | cgiFreeResources(); 265 | return -1; 266 | } 267 | #ifdef CGICDEBUG 268 | CGICDEBUGSTART 269 | fprintf(dout, "PostMultipartInput succeeded\n"); 270 | CGICDEBUGEND 271 | #endif /* CGICDEBUG */ 272 | } 273 | } else if (cgiStrEqNc(cgiRequestMethod, "get")) { 274 | /* The spec says this should be taken care of by 275 | the server, but... it isn't */ 276 | cgiContentLength = strlen(cgiQueryString); 277 | if (cgiParseGetFormInput() != cgiParseSuccess) { 278 | #ifdef CGICDEBUG 279 | CGICDEBUGSTART 280 | fprintf(dout, "GetFormInput failed\n"); 281 | CGICDEBUGEND 282 | #endif /* CGICDEBUG */ 283 | cgiHeaderStatus(500, "Error reading form data"); 284 | cgiFreeResources(); 285 | return -1; 286 | } else { 287 | #ifdef CGICDEBUG 288 | CGICDEBUGSTART 289 | fprintf(dout, "GetFormInput succeeded\n"); 290 | CGICDEBUGEND 291 | #endif /* CGICDEBUG */ 292 | } 293 | } 294 | #ifdef UNIT_TEST 295 | unitTest(); 296 | cgiFreeResources(); 297 | return 0; 298 | #else 299 | result = cgiMain(); 300 | return result; 301 | #endif 302 | } 303 | 304 | static void cgiGetenv(char **s, char *var){ 305 | *s = getenv(var); 306 | if (!(*s)) { 307 | *s = ""; 308 | } 309 | } 310 | 311 | static cgiParseResultType cgiParsePostFormInput() { 312 | char *input; 313 | cgiParseResultType result; 314 | if (!cgiContentLength) { 315 | return cgiParseSuccess; 316 | } 317 | input = (char *) malloc(cgiContentLength); 318 | if (!input) { 319 | return cgiParseMemory; 320 | } 321 | if (((int) fread(input, 1, cgiContentLength, cgiIn)) 322 | != cgiContentLength) 323 | { 324 | return cgiParseIO; 325 | } 326 | result = cgiParseFormInput(input, cgiContentLength); 327 | free(input); 328 | return result; 329 | } 330 | 331 | /* 2.0: A virtual datastream supporting putback of 332 | enough characters to handle multipart boundaries easily. 333 | A simple memset(&mp, 0, sizeof(mp)) is suitable initialization. */ 334 | 335 | typedef struct { 336 | /* Buffer for putting characters back */ 337 | char putback[1024]; 338 | /* Position in putback from which next character will be read. 339 | If readPos == writePos, then next character should 340 | come from cgiIn. */ 341 | int readPos; 342 | /* Position in putback to which next character will be put back. 343 | If writePos catches up to readPos, as opposed to the other 344 | way around, the stream no longer functions properly. 345 | Calling code must guarantee that no more than 346 | sizeof(putback) bytes are put back at any given time. */ 347 | int writePos; 348 | /* Offset in the virtual datastream; can be compared 349 | to cgiContentLength */ 350 | int offset; 351 | } mpStream, *mpStreamPtr; 352 | 353 | int mpRead(mpStreamPtr mpp, char *buffer, int len) 354 | { 355 | int ilen = len; 356 | int got = 0; 357 | /* Refuse to read past the declared length in order to 358 | avoid deadlock */ 359 | if (len > (cgiContentLength - mpp->offset)) { 360 | len = cgiContentLength - mpp->offset; 361 | } 362 | while (len) { 363 | if (mpp->readPos != mpp->writePos) { 364 | *buffer++ = mpp->putback[mpp->readPos++]; 365 | mpp->readPos %= sizeof(mpp->putback); 366 | got++; 367 | len--; 368 | } else { 369 | break; 370 | } 371 | } 372 | if (len) { 373 | int fgot = fread(buffer, 1, len, cgiIn); 374 | if (fgot >= 0) { 375 | mpp->offset += (got + fgot); 376 | return got + fgot; 377 | } else if (got > 0) { 378 | mpp->offset += got; 379 | return got; 380 | } else { 381 | /* EOF or error */ 382 | return fgot; 383 | } 384 | } else if (got) { 385 | mpp->offset += got; 386 | return got; 387 | } else if (ilen) { 388 | return EOF; 389 | } else { 390 | /* 2.01 */ 391 | return 0; 392 | } 393 | } 394 | 395 | void mpPutBack(mpStreamPtr mpp, char *data, int len) 396 | { 397 | mpp->offset -= len; 398 | while (len) { 399 | mpp->putback[mpp->writePos++] = *data++; 400 | mpp->writePos %= sizeof(mpp->putback); 401 | len--; 402 | } 403 | } 404 | 405 | /* This function copies the body to outf if it is not null, otherwise to 406 | a newly allocated character buffer at *outP, which will be null 407 | terminated; if both outf and outP are null the body is not stored. 408 | If bodyLengthP is not null, the size of the body in bytes is stored 409 | to *bodyLengthP, not including any terminating null added to *outP. 410 | If 'first' is nonzero, a preceding newline is not expected before 411 | the boundary. If 'first' is zero, a preceding newline is expected. 412 | Upon return mpp is positioned after the boundary and its trailing 413 | newline, if any; if the boundary is followed by -- the next two 414 | characters read after this function returns will be --. Upon error, 415 | if outP is not null, *outP is a null pointer; *bodyLengthP 416 | is set to zero. Returns cgiParseSuccess, cgiParseMemory 417 | or cgiParseIO. */ 418 | 419 | static cgiParseResultType afterNextBoundary(mpStreamPtr mpp, 420 | FILE *outf, 421 | char **outP, 422 | int *bodyLengthP, 423 | int first 424 | ); 425 | 426 | static int readHeaderLine( 427 | mpStreamPtr mpp, 428 | char *attr, 429 | int attrSpace, 430 | char *value, 431 | int valueSpace); 432 | 433 | static void decomposeValue(char *value, 434 | char *mvalue, int mvalueSpace, 435 | char **argNames, 436 | char **argValues, 437 | int argValueSpace); 438 | 439 | /* tfileName must be 1024 bytes to ensure adequacy on 440 | win32 (1024 exceeds the maximum path length and 441 | certainly exceeds observed behavior of _tmpnam). 442 | May as well also be 1024 bytes on Unix, although actual 443 | length is strlen(cgiTempDir) + a short unique pattern. */ 444 | 445 | static cgiParseResultType getTempFileName(char *tfileName); 446 | 447 | static cgiParseResultType cgiParsePostMultipartInput() { 448 | cgiParseResultType result; 449 | cgiFormEntry *n = 0, *l = 0; 450 | int got; 451 | FILE *outf = 0; 452 | char *out = 0; 453 | char tfileName[1024]; 454 | mpStream mp; 455 | mpStreamPtr mpp = ∓ 456 | memset(&mp, 0, sizeof(mp)); 457 | if (!cgiContentLength) { 458 | return cgiParseSuccess; 459 | } 460 | /* Read first boundary, including trailing newline */ 461 | result = afterNextBoundary(mpp, 0, 0, 0, 1); 462 | if (result == cgiParseIO) { 463 | /* An empty submission is not necessarily an error */ 464 | return cgiParseSuccess; 465 | } else if (result != cgiParseSuccess) { 466 | return result; 467 | } 468 | while (1) { 469 | char d[1024]; 470 | char fvalue[1024]; 471 | char fname[1024]; 472 | int bodyLength = 0; 473 | char ffileName[1024]; 474 | char fcontentType[1024]; 475 | char attr[1024]; 476 | char value[1024]; 477 | fvalue[0] = 0; 478 | fname[0] = 0; 479 | ffileName[0] = 0; 480 | fcontentType[0] = 0; 481 | out = 0; 482 | outf = 0; 483 | /* Check for EOF */ 484 | got = mpRead(mpp, d, 2); 485 | if (got < 2) { 486 | /* Crude EOF */ 487 | break; 488 | } 489 | if ((d[0] == '-') && (d[1] == '-')) { 490 | /* Graceful EOF */ 491 | break; 492 | } 493 | mpPutBack(mpp, d, 2); 494 | /* Read header lines until end of header */ 495 | while (readHeaderLine( 496 | mpp, attr, sizeof(attr), value, sizeof(value))) 497 | { 498 | char *argNames[3]; 499 | char *argValues[2]; 500 | /* Content-Disposition: form-data; 501 | name="test"; filename="googley.gif" */ 502 | if (cgiStrEqNc(attr, "Content-Disposition")) { 503 | argNames[0] = "name"; 504 | argNames[1] = "filename"; 505 | argNames[2] = 0; 506 | argValues[0] = fname; 507 | argValues[1] = ffileName; 508 | decomposeValue(value, 509 | fvalue, sizeof(fvalue), 510 | argNames, 511 | argValues, 512 | 1024); 513 | } else if (cgiStrEqNc(attr, "Content-Type")) { 514 | argNames[0] = 0; 515 | decomposeValue(value, 516 | fcontentType, sizeof(fcontentType), 517 | argNames, 518 | 0, 519 | 0); 520 | } 521 | } 522 | if (!cgiStrEqNc(fvalue, "form-data")) { 523 | /* Not form data */ 524 | result = afterNextBoundary(mpp, 0, 0, 0, 0); 525 | if (result != cgiParseSuccess) { 526 | /* Lack of a boundary here is an error. */ 527 | return result; 528 | } 529 | continue; 530 | } 531 | /* Body is everything from here until the next 532 | boundary. So, set it aside and move past boundary. 533 | If a filename was submitted as part of the 534 | disposition header, store to a temporary file. 535 | Otherwise, store to a memory buffer (it is 536 | presumably a regular form field). */ 537 | if (strlen(ffileName)) { 538 | if (getTempFileName(tfileName) != cgiParseSuccess) { 539 | return cgiParseIO; 540 | } 541 | outf = fopen(tfileName, "w+b"); 542 | } else { 543 | outf = 0; 544 | tfileName[0] = '\0'; 545 | } 546 | result = afterNextBoundary(mpp, outf, &out, &bodyLength, 0); 547 | if (result != cgiParseSuccess) { 548 | /* Lack of a boundary here is an error. */ 549 | if (outf) { 550 | fclose(outf); 551 | unlink(tfileName); 552 | } 553 | if (out) { 554 | free(out); 555 | } 556 | return result; 557 | } 558 | /* OK, we have a new pair, add it to the list. */ 559 | n = (cgiFormEntry *) malloc(sizeof(cgiFormEntry)); 560 | if (!n) { 561 | goto outOfMemory; 562 | } 563 | memset(n, 0, sizeof(cgiFormEntry)); 564 | /* 2.01: one of numerous new casts required 565 | to please C++ compilers */ 566 | n->attr = (char *) malloc(strlen(fname) + 1); 567 | if (!n->attr) { 568 | goto outOfMemory; 569 | } 570 | strcpy(n->attr, fname); 571 | if (out) { 572 | n->value = out; 573 | out = 0; 574 | } else if (outf) { 575 | n->value = (char *) malloc(1); 576 | if (!n->value) { 577 | goto outOfMemory; 578 | } 579 | n->value[0] = '\0'; 580 | fclose(outf); 581 | } 582 | n->valueLength = bodyLength; 583 | n->next = 0; 584 | if (!l) { 585 | cgiFormEntryFirst = n; 586 | } else { 587 | l->next = n; 588 | } 589 | n->fileName = (char *) malloc(strlen(ffileName) + 1); 590 | if (!n->fileName) { 591 | goto outOfMemory; 592 | } 593 | strcpy(n->fileName, ffileName); 594 | n->contentType = (char *) malloc(strlen(fcontentType) + 1); 595 | if (!n->contentType) { 596 | goto outOfMemory; 597 | } 598 | strcpy(n->contentType, fcontentType); 599 | n->tfileName = (char *) malloc(strlen(tfileName) + 1); 600 | if (!n->tfileName) { 601 | goto outOfMemory; 602 | } 603 | strcpy(n->tfileName, tfileName); 604 | 605 | l = n; 606 | } 607 | return cgiParseSuccess; 608 | outOfMemory: 609 | if (n) { 610 | if (n->attr) { 611 | free(n->attr); 612 | } 613 | if (n->value) { 614 | free(n->value); 615 | } 616 | if (n->fileName) { 617 | free(n->fileName); 618 | } 619 | if (n->tfileName) { 620 | free(n->tfileName); 621 | } 622 | if (n->contentType) { 623 | free(n->contentType); 624 | } 625 | free(n); 626 | } 627 | if (out) { 628 | free(out); 629 | } 630 | if (outf) { 631 | fclose(outf); 632 | unlink(tfileName); 633 | } 634 | return cgiParseMemory; 635 | } 636 | 637 | static cgiParseResultType getTempFileName(char *tfileName) 638 | { 639 | #ifndef WIN32 640 | /* Unix. Use the robust 'mkstemp' function to create 641 | a temporary file that is truly unique, with 642 | permissions that are truly safe. The 643 | fopen-for-write destroys any bogus information 644 | written by potential hackers during the brief 645 | window between the file's creation and the 646 | chmod call (glibc 2.0.6 and lower might 647 | otherwise have allowed this). */ 648 | int outfd; 649 | strcpy(tfileName, cgicTempDir "/cgicXXXXXX"); 650 | outfd = mkstemp(tfileName); 651 | if (outfd == -1) { 652 | return cgiParseIO; 653 | } 654 | close(outfd); 655 | /* Fix the permissions */ 656 | if (chmod(tfileName, 0600) != 0) { 657 | unlink(tfileName); 658 | return cgiParseIO; 659 | } 660 | #else 661 | /* Non-Unix. Do what we can. */ 662 | if (!tmpnam(tfileName)) { 663 | return cgiParseIO; 664 | } 665 | #endif 666 | return cgiParseSuccess; 667 | } 668 | 669 | 670 | #define APPEND(string, char) \ 671 | { \ 672 | if ((string##Len + 1) < string##Space) { \ 673 | string[string##Len++] = (char); \ 674 | } \ 675 | } 676 | 677 | #define RAPPEND(string, ch) \ 678 | { \ 679 | if ((string##Len + 1) == string##Space) { \ 680 | char *sold = string; \ 681 | string##Space *= 2; \ 682 | string = (char *) realloc(string, string##Space); \ 683 | if (!string) { \ 684 | string = sold; \ 685 | goto outOfMemory; \ 686 | } \ 687 | } \ 688 | string[string##Len++] = (ch); \ 689 | } 690 | 691 | #define BAPPEND(ch) \ 692 | { \ 693 | if (outf) { \ 694 | putc(ch, outf); \ 695 | outLen++; \ 696 | } else if (out) { \ 697 | RAPPEND(out, ch); \ 698 | } \ 699 | } 700 | 701 | cgiParseResultType afterNextBoundary(mpStreamPtr mpp, FILE *outf, char **outP, 702 | int *bodyLengthP, int first) 703 | { 704 | int outLen = 0; 705 | int outSpace = 256; 706 | char *out = 0; 707 | cgiParseResultType result; 708 | int boffset; 709 | int got; 710 | char d[2]; 711 | /* This is large enough, because the buffer into which the 712 | original boundary string is fetched is shorter by more 713 | than four characters due to the space required for 714 | the attribute name */ 715 | char workingBoundaryData[1024]; 716 | char *workingBoundary = workingBoundaryData; 717 | int workingBoundaryLength; 718 | if ((!outf) && (outP)) { 719 | out = (char *) malloc(outSpace); 720 | if (!out) { 721 | goto outOfMemory; 722 | } 723 | } 724 | boffset = 0; 725 | sprintf(workingBoundaryData, "\r\n--%s", cgiMultipartBoundary); 726 | if (first) { 727 | workingBoundary = workingBoundaryData + 2; 728 | } 729 | workingBoundaryLength = strlen(workingBoundary); 730 | while (1) { 731 | got = mpRead(mpp, d, 1); 732 | if (got != 1) { 733 | /* 2.01: cgiParseIO, not cgiFormIO */ 734 | result = cgiParseIO; 735 | goto error; 736 | } 737 | if (d[0] == workingBoundary[boffset]) { 738 | /* We matched the next byte of the boundary. 739 | Keep track of our progress into the 740 | boundary and don't emit anything. */ 741 | boffset++; 742 | if (boffset == workingBoundaryLength) { 743 | break; 744 | } 745 | } else if (boffset > 0) { 746 | /* We matched part, but not all, of the 747 | boundary. Now we have to be careful: 748 | put back all except the first 749 | character and try again. The 750 | real boundary could begin in the 751 | middle of a false match. We can 752 | emit the first character only so far. */ 753 | BAPPEND(workingBoundary[0]); 754 | mpPutBack(mpp, 755 | workingBoundary + 1, boffset - 1); 756 | mpPutBack(mpp, d, 1); 757 | boffset = 0; 758 | } else { 759 | /* Not presently in the middle of a boundary 760 | match; just emit the character. */ 761 | BAPPEND(d[0]); 762 | } 763 | } 764 | /* Read trailing newline or -- EOF marker. A literal EOF here 765 | would be an error in the input stream. */ 766 | got = mpRead(mpp, d, 2); 767 | if (got != 2) { 768 | result = cgiParseIO; 769 | goto error; 770 | } 771 | if ((d[0] == '\r') && (d[1] == '\n')) { 772 | /* OK, EOL */ 773 | } else if (d[0] == '-') { 774 | /* Probably EOF, but we check for 775 | that later */ 776 | mpPutBack(mpp, d, 2); 777 | } 778 | if (out && outSpace) { 779 | char *oout = out; 780 | out[outLen] = '\0'; 781 | out = (char *) realloc(out, outLen + 1); 782 | if (!out) { 783 | /* Surprising if it happens; and not fatal! We were 784 | just trying to give some space back. We can 785 | keep it if we have to. */ 786 | out = oout; 787 | } 788 | *outP = out; 789 | } 790 | if (bodyLengthP) { 791 | *bodyLengthP = outLen; 792 | } 793 | return cgiParseSuccess; 794 | outOfMemory: 795 | result = cgiParseMemory; 796 | if (outP) { 797 | if (out) { 798 | free(out); 799 | } 800 | *outP = 0; 801 | } 802 | error: 803 | if (bodyLengthP) { 804 | *bodyLengthP = 0; 805 | } 806 | if (out) { 807 | free(out); 808 | } 809 | if (outP) { 810 | *outP = 0; 811 | } 812 | return result; 813 | } 814 | 815 | static void decomposeValue(char *value, 816 | char *mvalue, int mvalueSpace, 817 | char **argNames, 818 | char **argValues, 819 | int argValueSpace) 820 | { 821 | char argName[1024]; 822 | int argNameSpace = sizeof(argName); 823 | int argNameLen = 0; 824 | int mvalueLen = 0; 825 | char *argValue; 826 | int argNum = 0; 827 | while (argNames[argNum]) { 828 | if (argValueSpace) { 829 | argValues[argNum][0] = '\0'; 830 | } 831 | argNum++; 832 | } 833 | while (isspace(*value)) { 834 | value++; 835 | } 836 | /* Quoted mvalue */ 837 | if (*value == '\"') { 838 | value++; 839 | while ((*value) && (*value != '\"')) { 840 | APPEND(mvalue, *value); 841 | value++; 842 | } 843 | while ((*value) && (*value != ';')) { 844 | value++; 845 | } 846 | } else { 847 | /* Unquoted mvalue */ 848 | while ((*value) && (*value != ';')) { 849 | APPEND(mvalue, *value); 850 | value++; 851 | } 852 | } 853 | if (mvalueSpace) { 854 | mvalue[mvalueLen] = '\0'; 855 | } 856 | while (*value == ';') { 857 | int argNum; 858 | int argValueLen = 0; 859 | /* Skip the ; between parameters */ 860 | value++; 861 | /* Now skip leading whitespace */ 862 | while ((*value) && (isspace(*value))) { 863 | value++; 864 | } 865 | /* Now read the parameter name */ 866 | argNameLen = 0; 867 | while ((*value) && (isalnum(*value))) { 868 | APPEND(argName, *value); 869 | value++; 870 | } 871 | if (argNameSpace) { 872 | argName[argNameLen] = '\0'; 873 | } 874 | while ((*value) && isspace(*value)) { 875 | value++; 876 | } 877 | if (*value != '=') { 878 | /* Malformed line */ 879 | return; 880 | } 881 | value++; 882 | while ((*value) && isspace(*value)) { 883 | value++; 884 | } 885 | /* Find the parameter in the argument list, if present */ 886 | argNum = 0; 887 | argValue = 0; 888 | while (argNames[argNum]) { 889 | if (cgiStrEqNc(argName, argNames[argNum])) { 890 | argValue = argValues[argNum]; 891 | break; 892 | } 893 | argNum++; 894 | } 895 | /* Finally, read the parameter value */ 896 | if (*value == '\"') { 897 | value++; 898 | while ((*value) && (*value != '\"')) { 899 | if (argValue) { 900 | APPEND(argValue, *value); 901 | } 902 | value++; 903 | } 904 | while ((*value) && (*value != ';')) { 905 | value++; 906 | } 907 | } else { 908 | /* Unquoted value */ 909 | while ((*value) && (*value != ';')) { 910 | if (argNames[argNum]) { 911 | APPEND(argValue, *value); 912 | } 913 | value++; 914 | } 915 | } 916 | if (argValueSpace) { 917 | if (argValue) { 918 | argValue[argValueLen] = '\0'; 919 | } 920 | } 921 | } 922 | } 923 | 924 | static int readHeaderLine( 925 | mpStreamPtr mpp, 926 | char *attr, 927 | int attrSpace, 928 | char *value, 929 | int valueSpace) 930 | { 931 | int attrLen = 0; 932 | int valueLen = 0; 933 | int valueFound = 0; 934 | while (1) { 935 | char d[1]; 936 | int got = mpRead(mpp, d, 1); 937 | if (got != 1) { 938 | return 0; 939 | } 940 | if (d[0] == '\r') { 941 | got = mpRead(mpp, d, 1); 942 | if (got == 1) { 943 | if (d[0] == '\n') { 944 | /* OK */ 945 | } else { 946 | mpPutBack(mpp, d, 1); 947 | } 948 | } 949 | break; 950 | } else if (d[0] == '\n') { 951 | break; 952 | } else if ((d[0] == ':') && attrLen) { 953 | valueFound = 1; 954 | while (mpRead(mpp, d, 1) == 1) { 955 | if (!isspace(d[0])) { 956 | mpPutBack(mpp, d, 1); 957 | break; 958 | } 959 | } 960 | } else if (!valueFound) { 961 | if (!isspace(*d)) { 962 | if (attrLen < (attrSpace - 1)) { 963 | attr[attrLen++] = *d; 964 | } 965 | } 966 | } else if (valueFound) { 967 | if (valueLen < (valueSpace - 1)) { 968 | value[valueLen++] = *d; 969 | } 970 | } 971 | } 972 | if (attrSpace) { 973 | attr[attrLen] = '\0'; 974 | } 975 | if (valueSpace) { 976 | value[valueLen] = '\0'; 977 | } 978 | if (attrLen && valueLen) { 979 | return 1; 980 | } else { 981 | return 0; 982 | } 983 | } 984 | 985 | static cgiParseResultType cgiParseGetFormInput() { 986 | return cgiParseFormInput(cgiQueryString, cgiContentLength); 987 | } 988 | 989 | typedef enum { 990 | cgiEscapeRest, 991 | cgiEscapeFirst, 992 | cgiEscapeSecond 993 | } cgiEscapeState; 994 | 995 | typedef enum { 996 | cgiUnescapeSuccess, 997 | cgiUnescapeMemory 998 | } cgiUnescapeResultType; 999 | 1000 | static cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len); 1001 | 1002 | static cgiParseResultType cgiParseFormInput(char *data, int length) { 1003 | /* Scan for pairs, unescaping and storing them as they are found. */ 1004 | int pos = 0; 1005 | cgiFormEntry *n; 1006 | cgiFormEntry *l = 0; 1007 | while (pos != length) { 1008 | int foundAmp = 0; 1009 | int start = pos; 1010 | int len = 0; 1011 | char *attr; 1012 | char *value; 1013 | while (pos != length) { 1014 | if (data[pos] == '&') { 1015 | /* Tolerate attr name without a value. This will fall through 1016 | and give us an empty value */ 1017 | break; 1018 | } 1019 | if (data[pos] == '=') { 1020 | pos++; 1021 | break; 1022 | } 1023 | pos++; 1024 | len++; 1025 | } 1026 | if (!len) { 1027 | break; 1028 | } 1029 | if (cgiUnescapeChars(&attr, data+start, len) 1030 | != cgiUnescapeSuccess) { 1031 | return cgiParseMemory; 1032 | } 1033 | start = pos; 1034 | len = 0; 1035 | while (pos != length) { 1036 | if (data[pos] == '&') { 1037 | foundAmp = 1; 1038 | pos++; 1039 | break; 1040 | } 1041 | pos++; 1042 | len++; 1043 | } 1044 | /* The last pair probably won't be followed by a &, but 1045 | that's fine, so check for that after accepting it */ 1046 | if (cgiUnescapeChars(&value, data+start, len) 1047 | != cgiUnescapeSuccess) { 1048 | free(attr); 1049 | return cgiParseMemory; 1050 | } 1051 | /* OK, we have a new pair, add it to the list. */ 1052 | n = (cgiFormEntry *) malloc(sizeof(cgiFormEntry)); 1053 | if (!n) { 1054 | free(attr); 1055 | free(value); 1056 | return cgiParseMemory; 1057 | } 1058 | n->attr = attr; 1059 | n->value = value; 1060 | n->valueLength = strlen(n->value); 1061 | n->fileName = (char *) malloc(1); 1062 | if (!n->fileName) { 1063 | free(attr); 1064 | free(value); 1065 | free(n); 1066 | return cgiParseMemory; 1067 | } 1068 | n->fileName[0] = '\0'; 1069 | n->contentType = (char *) malloc(1); 1070 | if (!n->contentType) { 1071 | free(attr); 1072 | free(value); 1073 | free(n->fileName); 1074 | free(n); 1075 | return cgiParseMemory; 1076 | } 1077 | n->contentType[0] = '\0'; 1078 | n->tfileName = (char *) malloc(1); 1079 | if (!n->tfileName) { 1080 | free(attr); 1081 | free(value); 1082 | free(n->fileName); 1083 | free(n->contentType); 1084 | free(n); 1085 | return cgiParseMemory; 1086 | } 1087 | n->tfileName[0] = '\0'; 1088 | n->next = 0; 1089 | if (!l) { 1090 | cgiFormEntryFirst = n; 1091 | } else { 1092 | l->next = n; 1093 | } 1094 | l = n; 1095 | if (!foundAmp) { 1096 | break; 1097 | } 1098 | } 1099 | return cgiParseSuccess; 1100 | } 1101 | 1102 | static int cgiHexValue[256]; 1103 | 1104 | cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len) { 1105 | char *s; 1106 | cgiEscapeState escapeState = cgiEscapeRest; 1107 | int escapedValue = 0; 1108 | int srcPos = 0; 1109 | int dstPos = 0; 1110 | s = (char *) malloc(len + 1); 1111 | if (!s) { 1112 | return cgiUnescapeMemory; 1113 | } 1114 | while (srcPos < len) { 1115 | int ch = cp[srcPos]; 1116 | switch (escapeState) { 1117 | case cgiEscapeRest: 1118 | if (ch == '%') { 1119 | escapeState = cgiEscapeFirst; 1120 | } else if (ch == '+') { 1121 | s[dstPos++] = ' '; 1122 | } else { 1123 | s[dstPos++] = ch; 1124 | } 1125 | break; 1126 | case cgiEscapeFirst: 1127 | escapedValue = cgiHexValue[ch] << 4; 1128 | escapeState = cgiEscapeSecond; 1129 | break; 1130 | case cgiEscapeSecond: 1131 | escapedValue += cgiHexValue[ch]; 1132 | s[dstPos++] = escapedValue; 1133 | escapeState = cgiEscapeRest; 1134 | break; 1135 | } 1136 | srcPos++; 1137 | } 1138 | s[dstPos] = '\0'; 1139 | *sp = s; 1140 | return cgiUnescapeSuccess; 1141 | } 1142 | 1143 | static void cgiSetupConstants() { 1144 | int i; 1145 | for (i=0; (i < 256); i++) { 1146 | cgiHexValue[i] = 0; 1147 | } 1148 | cgiHexValue['0'] = 0; 1149 | cgiHexValue['1'] = 1; 1150 | cgiHexValue['2'] = 2; 1151 | cgiHexValue['3'] = 3; 1152 | cgiHexValue['4'] = 4; 1153 | cgiHexValue['5'] = 5; 1154 | cgiHexValue['6'] = 6; 1155 | cgiHexValue['7'] = 7; 1156 | cgiHexValue['8'] = 8; 1157 | cgiHexValue['9'] = 9; 1158 | cgiHexValue['A'] = 10; 1159 | cgiHexValue['B'] = 11; 1160 | cgiHexValue['C'] = 12; 1161 | cgiHexValue['D'] = 13; 1162 | cgiHexValue['E'] = 14; 1163 | cgiHexValue['F'] = 15; 1164 | cgiHexValue['a'] = 10; 1165 | cgiHexValue['b'] = 11; 1166 | cgiHexValue['c'] = 12; 1167 | cgiHexValue['d'] = 13; 1168 | cgiHexValue['e'] = 14; 1169 | cgiHexValue['f'] = 15; 1170 | } 1171 | 1172 | static void cgiFreeResources() { 1173 | cgiFormEntry *c = cgiFormEntryFirst; 1174 | cgiFormEntry *n; 1175 | while (c) { 1176 | n = c->next; 1177 | free(c->attr); 1178 | free(c->value); 1179 | free(c->fileName); 1180 | free(c->contentType); 1181 | if (strlen(c->tfileName)) { 1182 | unlink(c->tfileName); 1183 | } 1184 | free(c->tfileName); 1185 | free(c); 1186 | c = n; 1187 | } 1188 | /* If the cgi environment was restored from a saved environment, 1189 | then these are in allocated space and must also be freed */ 1190 | if (cgiRestored) { 1191 | free(cgiServerSoftware); 1192 | free(cgiServerName); 1193 | free(cgiGatewayInterface); 1194 | free(cgiServerProtocol); 1195 | free(cgiServerPort); 1196 | free(cgiRequestMethod); 1197 | free(cgiPathInfo); 1198 | free(cgiPathTranslated); 1199 | free(cgiScriptName); 1200 | free(cgiQueryString); 1201 | free(cgiRemoteHost); 1202 | free(cgiRemoteAddr); 1203 | free(cgiAuthType); 1204 | free(cgiRemoteUser); 1205 | free(cgiRemoteIdent); 1206 | free(cgiContentType); 1207 | free(cgiAccept); 1208 | free(cgiUserAgent); 1209 | free(cgiReferrer); 1210 | } 1211 | /* 2.0: to clean up the environment for cgiReadEnvironment, 1212 | we must set these correctly */ 1213 | cgiFormEntryFirst = 0; 1214 | cgiRestored = 0; 1215 | } 1216 | 1217 | static cgiFormResultType cgiFormEntryString( 1218 | cgiFormEntry *e, char *result, int max, int newlines); 1219 | 1220 | static cgiFormEntry *cgiFormEntryFindFirst(char *name); 1221 | static cgiFormEntry *cgiFormEntryFindNext(); 1222 | 1223 | cgiFormResultType cgiFormString( 1224 | char *name, char *result, int max) { 1225 | cgiFormEntry *e; 1226 | e = cgiFormEntryFindFirst(name); 1227 | if (!e) { 1228 | strcpy(result, ""); 1229 | return cgiFormNotFound; 1230 | } 1231 | return cgiFormEntryString(e, result, max, 1); 1232 | } 1233 | 1234 | cgiFormResultType cgiFormFileName( 1235 | char *name, char *result, int resultSpace) 1236 | { 1237 | cgiFormEntry *e; 1238 | int resultLen = 0; 1239 | char *s; 1240 | e = cgiFormEntryFindFirst(name); 1241 | if (!e) { 1242 | strcpy(result, ""); 1243 | return cgiFormNotFound; 1244 | } 1245 | s = e->fileName; 1246 | while (*s) { 1247 | APPEND(result, *s); 1248 | s++; 1249 | } 1250 | if (resultSpace) { 1251 | result[resultLen] = '\0'; 1252 | } 1253 | if (!strlen(e->fileName)) { 1254 | return cgiFormNoFileName; 1255 | } else if (((int) strlen(e->fileName)) > (resultSpace - 1)) { 1256 | return cgiFormTruncated; 1257 | } else { 1258 | return cgiFormSuccess; 1259 | } 1260 | } 1261 | 1262 | cgiFormResultType cgiFormFileContentType( 1263 | char *name, char *result, int resultSpace) 1264 | { 1265 | cgiFormEntry *e; 1266 | int resultLen = 0; 1267 | char *s; 1268 | e = cgiFormEntryFindFirst(name); 1269 | if (!e) { 1270 | if (resultSpace) { 1271 | result[0] = '\0'; 1272 | } 1273 | return cgiFormNotFound; 1274 | } 1275 | s = e->contentType; 1276 | while (*s) { 1277 | APPEND(result, *s); 1278 | s++; 1279 | } 1280 | if (resultSpace) { 1281 | result[resultLen] = '\0'; 1282 | } 1283 | if (!strlen(e->contentType)) { 1284 | return cgiFormNoContentType; 1285 | } else if (((int) strlen(e->contentType)) > (resultSpace - 1)) { 1286 | return cgiFormTruncated; 1287 | } else { 1288 | return cgiFormSuccess; 1289 | } 1290 | } 1291 | 1292 | cgiFormResultType cgiFormFileSize( 1293 | char *name, int *sizeP) 1294 | { 1295 | cgiFormEntry *e; 1296 | e = cgiFormEntryFindFirst(name); 1297 | if (!e) { 1298 | if (sizeP) { 1299 | *sizeP = 0; 1300 | } 1301 | return cgiFormNotFound; 1302 | } else if (!strlen(e->tfileName)) { 1303 | if (sizeP) { 1304 | *sizeP = 0; 1305 | } 1306 | return cgiFormNotAFile; 1307 | } else { 1308 | if (sizeP) { 1309 | *sizeP = e->valueLength; 1310 | } 1311 | return cgiFormSuccess; 1312 | } 1313 | } 1314 | 1315 | typedef struct cgiFileStruct { 1316 | FILE *in; 1317 | } cgiFile; 1318 | 1319 | cgiFormResultType cgiFormFileOpen( 1320 | char *name, cgiFilePtr *cfpp) 1321 | { 1322 | cgiFormEntry *e; 1323 | cgiFilePtr cfp; 1324 | e = cgiFormEntryFindFirst(name); 1325 | if (!e) { 1326 | *cfpp = 0; 1327 | return cgiFormNotFound; 1328 | } 1329 | if (!strlen(e->tfileName)) { 1330 | *cfpp = 0; 1331 | return cgiFormNotAFile; 1332 | } 1333 | cfp = (cgiFilePtr) malloc(sizeof(cgiFile)); 1334 | if (!cfp) { 1335 | *cfpp = 0; 1336 | return cgiFormMemory; 1337 | } 1338 | cfp->in = fopen(e->tfileName, "rb"); 1339 | if (!cfp->in) { 1340 | free(cfp); 1341 | return cgiFormIO; 1342 | } 1343 | *cfpp = cfp; 1344 | return cgiFormSuccess; 1345 | } 1346 | 1347 | cgiFormResultType cgiFormFileRead( 1348 | cgiFilePtr cfp, char *buffer, 1349 | int bufferSize, int *gotP) 1350 | { 1351 | int got = 0; 1352 | if (!cfp) { 1353 | return cgiFormOpenFailed; 1354 | } 1355 | got = fread(buffer, 1, bufferSize, cfp->in); 1356 | if (got <= 0) { 1357 | return cgiFormEOF; 1358 | } 1359 | *gotP = got; 1360 | return cgiFormSuccess; 1361 | } 1362 | 1363 | cgiFormResultType cgiFormFileClose(cgiFilePtr cfp) 1364 | { 1365 | if (!cfp) { 1366 | return cgiFormOpenFailed; 1367 | } 1368 | fclose(cfp->in); 1369 | free(cfp); 1370 | return cgiFormSuccess; 1371 | } 1372 | 1373 | cgiFormResultType cgiFormStringNoNewlines( 1374 | char *name, char *result, int max) { 1375 | cgiFormEntry *e; 1376 | e = cgiFormEntryFindFirst(name); 1377 | if (!e) { 1378 | strcpy(result, ""); 1379 | return cgiFormNotFound; 1380 | } 1381 | return cgiFormEntryString(e, result, max, 0); 1382 | } 1383 | 1384 | cgiFormResultType cgiFormStringMultiple( 1385 | char *name, char ***result) { 1386 | char **stringArray; 1387 | cgiFormEntry *e; 1388 | int i; 1389 | int total = 0; 1390 | /* Make two passes. One would be more efficient, but this 1391 | function is not commonly used. The select menu and 1392 | radio box functions are faster. */ 1393 | e = cgiFormEntryFindFirst(name); 1394 | if (e != 0) { 1395 | do { 1396 | total++; 1397 | } while ((e = cgiFormEntryFindNext()) != 0); 1398 | } 1399 | stringArray = (char **) malloc(sizeof(char *) * (total + 1)); 1400 | if (!stringArray) { 1401 | *result = 0; 1402 | return cgiFormMemory; 1403 | } 1404 | /* initialize all entries to null; the last will stay that way */ 1405 | for (i=0; (i <= total); i++) { 1406 | stringArray[i] = 0; 1407 | } 1408 | /* Now go get the entries */ 1409 | e = cgiFormEntryFindFirst(name); 1410 | #ifdef CGICDEBUG 1411 | CGICDEBUGSTART 1412 | fprintf(dout, "StringMultiple Beginning\n"); 1413 | CGICDEBUGEND 1414 | #endif /* CGICDEBUG */ 1415 | if (e) { 1416 | i = 0; 1417 | do { 1418 | int max = (int) (strlen(e->value) + 1); 1419 | stringArray[i] = (char *) malloc(max); 1420 | if (stringArray[i] == 0) { 1421 | /* Memory problems */ 1422 | cgiStringArrayFree(stringArray); 1423 | *result = 0; 1424 | return cgiFormMemory; 1425 | } 1426 | strcpy(stringArray[i], e->value); 1427 | cgiFormEntryString(e, stringArray[i], max, 1); 1428 | i++; 1429 | } while ((e = cgiFormEntryFindNext()) != 0); 1430 | *result = stringArray; 1431 | #ifdef CGICDEBUG 1432 | CGICDEBUGSTART 1433 | fprintf(dout, "StringMultiple Succeeding\n"); 1434 | CGICDEBUGEND 1435 | #endif /* CGICDEBUG */ 1436 | return cgiFormSuccess; 1437 | } else { 1438 | *result = stringArray; 1439 | #ifdef CGICDEBUG 1440 | CGICDEBUGSTART 1441 | fprintf(dout, "StringMultiple found nothing\n"); 1442 | CGICDEBUGEND 1443 | #endif /* CGICDEBUG */ 1444 | return cgiFormNotFound; 1445 | } 1446 | } 1447 | 1448 | cgiFormResultType cgiFormStringSpaceNeeded( 1449 | char *name, int *result) { 1450 | cgiFormEntry *e; 1451 | e = cgiFormEntryFindFirst(name); 1452 | if (!e) { 1453 | *result = 1; 1454 | return cgiFormNotFound; 1455 | } 1456 | *result = ((int) strlen(e->value)) + 1; 1457 | return cgiFormSuccess; 1458 | } 1459 | 1460 | static cgiFormResultType cgiFormEntryString( 1461 | cgiFormEntry *e, char *result, int max, int newlines) { 1462 | char *dp, *sp; 1463 | int truncated = 0; 1464 | int len = 0; 1465 | int avail = max-1; 1466 | int crCount = 0; 1467 | int lfCount = 0; 1468 | dp = result; 1469 | sp = e->value; 1470 | while (1) { 1471 | int ch; 1472 | /* 1.07: don't check for available space now. 1473 | We check for it immediately before adding 1474 | an actual character. 1.06 handled the 1475 | trailing null of the source string improperly, 1476 | resulting in a cgiFormTruncated error. */ 1477 | ch = *sp; 1478 | /* Fix the CR/LF, LF, CR nightmare: watch for 1479 | consecutive bursts of CRs and LFs in whatever 1480 | pattern, then actually output the larger number 1481 | of LFs. Consistently sane, yet it still allows 1482 | consecutive blank lines when the user 1483 | actually intends them. */ 1484 | if ((ch == 13) || (ch == 10)) { 1485 | if (ch == 13) { 1486 | crCount++; 1487 | } else { 1488 | lfCount++; 1489 | } 1490 | } else { 1491 | if (crCount || lfCount) { 1492 | int lfsAdd = crCount; 1493 | if (lfCount > crCount) { 1494 | lfsAdd = lfCount; 1495 | } 1496 | /* Stomp all newlines if desired */ 1497 | if (!newlines) { 1498 | lfsAdd = 0; 1499 | } 1500 | while (lfsAdd) { 1501 | if (len >= avail) { 1502 | truncated = 1; 1503 | break; 1504 | } 1505 | *dp = 10; 1506 | dp++; 1507 | lfsAdd--; 1508 | len++; 1509 | } 1510 | crCount = 0; 1511 | lfCount = 0; 1512 | } 1513 | if (ch == '\0') { 1514 | /* The end of the source string */ 1515 | break; 1516 | } 1517 | /* 1.06: check available space before adding 1518 | the character, because a previously added 1519 | LF may have brought us to the limit */ 1520 | if (len >= avail) { 1521 | truncated = 1; 1522 | break; 1523 | } 1524 | *dp = ch; 1525 | dp++; 1526 | len++; 1527 | } 1528 | sp++; 1529 | } 1530 | *dp = '\0'; 1531 | if (truncated) { 1532 | return cgiFormTruncated; 1533 | } else if (!len) { 1534 | return cgiFormEmpty; 1535 | } else { 1536 | return cgiFormSuccess; 1537 | } 1538 | } 1539 | 1540 | static int cgiFirstNonspaceChar(char *s); 1541 | 1542 | cgiFormResultType cgiFormInteger( 1543 | char *name, int *result, int defaultV) { 1544 | cgiFormEntry *e; 1545 | int ch; 1546 | e = cgiFormEntryFindFirst(name); 1547 | if (!e) { 1548 | *result = defaultV; 1549 | return cgiFormNotFound; 1550 | } 1551 | if (!strlen(e->value)) { 1552 | *result = defaultV; 1553 | return cgiFormEmpty; 1554 | } 1555 | ch = cgiFirstNonspaceChar(e->value); 1556 | if (!(isdigit(ch)) && (ch != '-') && (ch != '+')) { 1557 | *result = defaultV; 1558 | return cgiFormBadType; 1559 | } else { 1560 | *result = atoi(e->value); 1561 | return cgiFormSuccess; 1562 | } 1563 | } 1564 | 1565 | cgiFormResultType cgiFormIntegerBounded( 1566 | char *name, int *result, int min, int max, int defaultV) { 1567 | cgiFormResultType error = cgiFormInteger(name, result, defaultV); 1568 | if (error != cgiFormSuccess) { 1569 | return error; 1570 | } 1571 | if (*result < min) { 1572 | *result = min; 1573 | return cgiFormConstrained; 1574 | } 1575 | if (*result > max) { 1576 | *result = max; 1577 | return cgiFormConstrained; 1578 | } 1579 | return cgiFormSuccess; 1580 | } 1581 | 1582 | cgiFormResultType cgiFormDouble( 1583 | char *name, double *result, double defaultV) { 1584 | cgiFormEntry *e; 1585 | int ch; 1586 | e = cgiFormEntryFindFirst(name); 1587 | if (!e) { 1588 | *result = defaultV; 1589 | return cgiFormNotFound; 1590 | } 1591 | if (!strlen(e->value)) { 1592 | *result = defaultV; 1593 | return cgiFormEmpty; 1594 | } 1595 | ch = cgiFirstNonspaceChar(e->value); 1596 | if (!(isdigit(ch)) && (ch != '.') && (ch != '-') && (ch != '+')) { 1597 | *result = defaultV; 1598 | return cgiFormBadType; 1599 | } else { 1600 | *result = atof(e->value); 1601 | return cgiFormSuccess; 1602 | } 1603 | } 1604 | 1605 | cgiFormResultType cgiFormDoubleBounded( 1606 | char *name, double *result, double min, double max, double defaultV) { 1607 | cgiFormResultType error = cgiFormDouble(name, result, defaultV); 1608 | if (error != cgiFormSuccess) { 1609 | return error; 1610 | } 1611 | if (*result < min) { 1612 | *result = min; 1613 | return cgiFormConstrained; 1614 | } 1615 | if (*result > max) { 1616 | *result = max; 1617 | return cgiFormConstrained; 1618 | } 1619 | return cgiFormSuccess; 1620 | } 1621 | 1622 | cgiFormResultType cgiFormSelectSingle( 1623 | char *name, char choicesText[][20], int choicesTotal, 1624 | int *result, int defaultV) 1625 | { 1626 | cgiFormEntry *e; 1627 | int i; 1628 | e = cgiFormEntryFindFirst(name); 1629 | #ifdef CGICDEBUG 1630 | CGICDEBUGSTART 1631 | CGICDEBUGEND 1632 | #endif /* CGICDEBUG */ 1633 | if (!e) { 1634 | *result = defaultV; 1635 | return cgiFormNotFound; 1636 | } 1637 | for (i=0; (i < choicesTotal); i++) { 1638 | #ifdef CGICDEBUG 1639 | CGICDEBUGSTART 1640 | fprintf(dout, "%s %s\n", choicesText[i], e->value); 1641 | CGICDEBUGEND 1642 | #endif /* CGICDEBUG */ 1643 | if (cgiStrEq(choicesText[i], e->value)) { 1644 | #ifdef CGICDEBUG 1645 | CGICDEBUGSTART 1646 | fprintf(dout, "MATCH\n"); 1647 | CGICDEBUGEND 1648 | #endif /* CGICDEBUG */ 1649 | *result = i; 1650 | return cgiFormSuccess; 1651 | } 1652 | } 1653 | *result = defaultV; 1654 | return cgiFormNoSuchChoice; 1655 | } 1656 | 1657 | #if 0 1658 | cgiFormResultType cgiFormSelectSingle( 1659 | char *name, char **choicesText, int choicesTotal, 1660 | int *result, int defaultV) 1661 | 1662 | { 1663 | cgiFormEntry *e; 1664 | int i; 1665 | e = cgiFormEntryFindFirst(name); 1666 | #ifdef CGICDEBUG 1667 | CGICDEBUGSTART 1668 | fprintf(cgiOut, "e=%d\n", (int) e); 1669 | CGICDEBUGEND 1670 | #endif /* CGICDEBUG */ 1671 | if (!e) { 1672 | *result = defaultV; 1673 | 1674 | fprintf(cgiOut, "finderr"); 1675 | return cgiFormNotFound; 1676 | } 1677 | fprintf(cgiOut, "inx=%s \n", e->value); 1678 | return; 1679 | for (i=0; (i < choicesTotal); i++) { 1680 | #ifdef CGICDEBUG 1681 | CGICDEBUGSTART 1682 | fprintf(dout, "%s %s\n", choicesText[i], e->value); 1683 | CGICDEBUGEND 1684 | #endif /* CGICDEBUG */ 1685 | if (cgiStrEq(choicesText[i], e->value)) { 1686 | #ifdef CGICDEBUG 1687 | CGICDEBUGSTART 1688 | fprintf(dout, "MATCH\n"); 1689 | CGICDEBUGEND 1690 | #endif /* CGICDEBUG */ 1691 | *result = i; 1692 | return cgiFormSuccess; 1693 | } 1694 | } 1695 | *result = defaultV; 1696 | return cgiFormNoSuchChoice; 1697 | } 1698 | 1699 | #endif 1700 | cgiFormResultType cgiFormSelectMultiple( 1701 | char *name, char **choicesText, int choicesTotal, 1702 | int *result, int *invalid) 1703 | { 1704 | cgiFormEntry *e; 1705 | int i; 1706 | int hits = 0; 1707 | int invalidE = 0; 1708 | for (i=0; (i < choicesTotal); i++) { 1709 | result[i] = 0; 1710 | } 1711 | e = cgiFormEntryFindFirst(name); 1712 | if (!e) { 1713 | *invalid = invalidE; 1714 | return cgiFormNotFound; 1715 | } 1716 | do { 1717 | int hit = 0; 1718 | for (i=0; (i < choicesTotal); i++) { 1719 | if (cgiStrEq(choicesText[i], e->value)) { 1720 | result[i] = 1; 1721 | hits++; 1722 | hit = 1; 1723 | break; 1724 | } 1725 | } 1726 | if (!(hit)) { 1727 | invalidE++; 1728 | } 1729 | } while ((e = cgiFormEntryFindNext()) != 0); 1730 | 1731 | *invalid = invalidE; 1732 | 1733 | if (hits) { 1734 | return cgiFormSuccess; 1735 | } else { 1736 | return cgiFormNotFound; 1737 | } 1738 | } 1739 | 1740 | cgiFormResultType cgiFormCheckboxSingle( 1741 | char *name) 1742 | { 1743 | cgiFormEntry *e; 1744 | e = cgiFormEntryFindFirst(name); 1745 | if (!e) { 1746 | return cgiFormNotFound; 1747 | } 1748 | return cgiFormSuccess; 1749 | } 1750 | 1751 | extern cgiFormResultType cgiFormCheckboxMultiple( 1752 | char *name, char **valuesText, int valuesTotal, 1753 | int *result, int *invalid) 1754 | { 1755 | /* Implementation is identical to cgiFormSelectMultiple. */ 1756 | return cgiFormSelectMultiple(name, valuesText, 1757 | valuesTotal, result, invalid); 1758 | } 1759 | 1760 | cgiFormResultType cgiFormRadio( 1761 | char *name, 1762 | char **valuesText, int valuesTotal, int *result, int defaultV) 1763 | { 1764 | /* Implementation is identical to cgiFormSelectSingle. */ 1765 | return cgiFormSelectSingle(name, valuesText, valuesTotal, 1766 | result, defaultV); 1767 | } 1768 | 1769 | cgiFormResultType cgiCookieString( 1770 | char *name, 1771 | char *value, 1772 | int space) 1773 | { 1774 | char *p = cgiCookie; 1775 | while (*p) { 1776 | char *n = name; 1777 | /* 2.02: if cgiCookie is exactly equal to name, this 1778 | can cause an overrun. The server probably wouldn't 1779 | allow it, since a name without values makes no sense 1780 | -- but then again it might not check, so this is a 1781 | genuine security concern. Thanks to Nicolas 1782 | Tomadakis. */ 1783 | while (*p == *n) { 1784 | if ((*p == '\0') && (*n == '\0')) { 1785 | /* Malformed cookie header from client */ 1786 | return cgiFormNotFound; 1787 | } 1788 | p++; 1789 | n++; 1790 | } 1791 | if ((!*n) && (*p == '=')) { 1792 | p++; 1793 | while ((*p != ';') && (*p != '\0') && 1794 | (space > 1)) 1795 | { 1796 | *value = *p; 1797 | value++; 1798 | p++; 1799 | space--; 1800 | } 1801 | if (space > 0) { 1802 | *value = '\0'; 1803 | } 1804 | /* Correct parens: 2.02. Thanks to 1805 | Mathieu Villeneuve-Belair. */ 1806 | if (!(((*p) == ';') || ((*p) == '\0'))) 1807 | { 1808 | return cgiFormTruncated; 1809 | } else { 1810 | return cgiFormSuccess; 1811 | } 1812 | } else { 1813 | /* Skip to next cookie */ 1814 | while (*p) { 1815 | if (*p == ';') { 1816 | break; 1817 | } 1818 | p++; 1819 | } 1820 | if (!*p) { 1821 | /* 2.01: default to empty */ 1822 | if (space) { 1823 | *value = '\0'; 1824 | } 1825 | return cgiFormNotFound; 1826 | } 1827 | p++; 1828 | /* Allow whitespace after semicolon */ 1829 | while ((*p) && isspace(*p)) { 1830 | p++; 1831 | } 1832 | } 1833 | } 1834 | /* 2.01: actually the above loop never terminates except 1835 | with a return, but do this to placate gcc */ 1836 | /* Actually, it can, so this is real. */ 1837 | if (space) { 1838 | *value = '\0'; 1839 | } 1840 | return cgiFormNotFound; 1841 | } 1842 | 1843 | cgiFormResultType cgiCookieInteger( 1844 | char *name, 1845 | int *result, 1846 | int defaultV) 1847 | { 1848 | char buffer[256]; 1849 | cgiFormResultType r = 1850 | cgiCookieString(name, buffer, sizeof(buffer)); 1851 | if (r != cgiFormSuccess) { 1852 | *result = defaultV; 1853 | } else { 1854 | *result = atoi(buffer); 1855 | } 1856 | return r; 1857 | } 1858 | 1859 | void cgiHeaderCookieSetInteger(char *name, int value, int secondsToLive, 1860 | char *path, char *domain) 1861 | { 1862 | char svalue[256]; 1863 | sprintf(svalue, "%d", value); 1864 | cgiHeaderCookieSetString(name, svalue, secondsToLive, path, domain); 1865 | } 1866 | 1867 | static char *days[] = { 1868 | "Sun", 1869 | "Mon", 1870 | "Tue", 1871 | "Wed", 1872 | "Thu", 1873 | "Fri", 1874 | "Sat" 1875 | }; 1876 | 1877 | static char *months[] = { 1878 | "Jan", 1879 | "Feb", 1880 | "Mar", 1881 | "Apr", 1882 | "May", 1883 | "Jun", 1884 | "Jul", 1885 | "Aug", 1886 | "Sep", 1887 | "Oct", 1888 | "Nov", 1889 | "Dec" 1890 | }; 1891 | 1892 | void cgiHeaderCookieSetString(char *name, char *value, int secondsToLive, 1893 | char *path, char *domain) 1894 | { 1895 | /* cgic 2.02: simpler and more widely compatible implementation. 1896 | Thanks to Chunfu Lai. 1897 | cgic 2.03: yes, but it didn't work. Reimplemented by 1898 | Thomas Boutell. ; after last element was a bug. 1899 | Examples of real world cookies that really work: 1900 | Set-Cookie: MSNADS=UM=; domain=.slate.com; 1901 | expires=Tue, 26-Apr-2022 19:00:00 GMT; path=/ 1902 | Set-Cookie: MC1=V=3&ID=b5bc08af2b8a43ff85fcb5efd8b238f0; 1903 | domain=.slate.com; expires=Mon, 04-Oct-2021 19:00:00 GMT; path=/ 1904 | */ 1905 | time_t now; 1906 | time_t then; 1907 | struct tm *gt; 1908 | time(&now); 1909 | then = now + secondsToLive; 1910 | gt = gmtime(&then); 1911 | fprintf(cgiOut, 1912 | "Set-Cookie: %s=%s; domain=%s; expires=%s, %02d-%s-%04d %02d:%02d:%02d GMT; path=%s\r\n", 1913 | name, value, domain, 1914 | days[gt->tm_wday], 1915 | gt->tm_mday, 1916 | months[gt->tm_mon], 1917 | gt->tm_year + 1900, 1918 | gt->tm_hour, 1919 | gt->tm_min, 1920 | gt->tm_sec, 1921 | path); 1922 | } 1923 | 1924 | void cgiHeaderLocation(char *redirectUrl) { 1925 | fprintf(cgiOut, "Location: %s\r\n\r\n", redirectUrl); 1926 | } 1927 | 1928 | void cgiHeaderStatus(int status, char *statusMessage) { 1929 | fprintf(cgiOut, "Status: %d %s\r\n\r\n", status, statusMessage); 1930 | } 1931 | 1932 | void cgiHeaderContentType(char *mimeType) { 1933 | fprintf(cgiOut, "Content-type: %s\r\n\r\n", mimeType); 1934 | } 1935 | 1936 | static int cgiWriteString(FILE *out, char *s); 1937 | 1938 | static int cgiWriteInt(FILE *out, int i); 1939 | 1940 | #define CGIC_VERSION "2.0" 1941 | 1942 | cgiEnvironmentResultType cgiWriteEnvironment(char *filename) { 1943 | FILE *out; 1944 | cgiFormEntry *e; 1945 | /* Be sure to open in binary mode */ 1946 | out = fopen(filename, "wb"); 1947 | if (!out) { 1948 | /* Can't create file */ 1949 | return cgiEnvironmentIO; 1950 | } 1951 | if (!cgiWriteString(out, "CGIC2.0")) { 1952 | goto error; 1953 | } 1954 | if (!cgiWriteString(out, cgiServerSoftware)) { 1955 | goto error; 1956 | } 1957 | if (!cgiWriteString(out, cgiServerName)) { 1958 | goto error; 1959 | } 1960 | if (!cgiWriteString(out, cgiGatewayInterface)) { 1961 | goto error; 1962 | } 1963 | if (!cgiWriteString(out, cgiServerProtocol)) { 1964 | goto error; 1965 | } 1966 | if (!cgiWriteString(out, cgiServerPort)) { 1967 | goto error; 1968 | } 1969 | if (!cgiWriteString(out, cgiRequestMethod)) { 1970 | goto error; 1971 | } 1972 | if (!cgiWriteString(out, cgiPathInfo)) { 1973 | goto error; 1974 | } 1975 | if (!cgiWriteString(out, cgiPathTranslated)) { 1976 | goto error; 1977 | } 1978 | if (!cgiWriteString(out, cgiScriptName)) { 1979 | goto error; 1980 | } 1981 | if (!cgiWriteString(out, cgiQueryString)) { 1982 | goto error; 1983 | } 1984 | if (!cgiWriteString(out, cgiRemoteHost)) { 1985 | goto error; 1986 | } 1987 | if (!cgiWriteString(out, cgiRemoteAddr)) { 1988 | goto error; 1989 | } 1990 | if (!cgiWriteString(out, cgiAuthType)) { 1991 | goto error; 1992 | } 1993 | if (!cgiWriteString(out, cgiRemoteUser)) { 1994 | goto error; 1995 | } 1996 | if (!cgiWriteString(out, cgiRemoteIdent)) { 1997 | goto error; 1998 | } 1999 | if (!cgiWriteString(out, cgiContentType)) { 2000 | goto error; 2001 | } 2002 | if (!cgiWriteString(out, cgiAccept)) { 2003 | goto error; 2004 | } 2005 | if (!cgiWriteString(out, cgiUserAgent)) { 2006 | goto error; 2007 | } 2008 | if (!cgiWriteString(out, cgiReferrer)) { 2009 | goto error; 2010 | } 2011 | if (!cgiWriteString(out, cgiCookie)) { 2012 | goto error; 2013 | } 2014 | if (!cgiWriteInt(out, cgiContentLength)) { 2015 | goto error; 2016 | } 2017 | e = cgiFormEntryFirst; 2018 | while (e) { 2019 | cgiFilePtr fp; 2020 | if (!cgiWriteString(out, e->attr)) { 2021 | goto error; 2022 | } 2023 | if (!cgiWriteString(out, e->value)) { 2024 | goto error; 2025 | } 2026 | /* New 2.0 fields and file uploads */ 2027 | if (!cgiWriteString(out, e->fileName)) { 2028 | goto error; 2029 | } 2030 | if (!cgiWriteString(out, e->contentType)) { 2031 | goto error; 2032 | } 2033 | if (!cgiWriteInt(out, e->valueLength)) { 2034 | goto error; 2035 | } 2036 | if (cgiFormFileOpen(e->attr, &fp) == cgiFormSuccess) { 2037 | char buffer[1024]; 2038 | int got; 2039 | if (!cgiWriteInt(out, 1)) { 2040 | cgiFormFileClose(fp); 2041 | goto error; 2042 | } 2043 | while (cgiFormFileRead(fp, buffer, 2044 | sizeof(buffer), &got) == cgiFormSuccess) 2045 | { 2046 | if (((int) fwrite(buffer, 1, got, out)) != got) { 2047 | cgiFormFileClose(fp); 2048 | goto error; 2049 | } 2050 | } 2051 | if (cgiFormFileClose(fp) != cgiFormSuccess) { 2052 | goto error; 2053 | } 2054 | } else { 2055 | if (!cgiWriteInt(out, 0)) { 2056 | goto error; 2057 | } 2058 | } 2059 | e = e->next; 2060 | } 2061 | fclose(out); 2062 | return cgiEnvironmentSuccess; 2063 | error: 2064 | fclose(out); 2065 | /* If this function is not defined in your system, 2066 | you must substitute the appropriate 2067 | file-deletion function. */ 2068 | unlink(filename); 2069 | return cgiEnvironmentIO; 2070 | } 2071 | 2072 | static int cgiWriteString(FILE *out, char *s) { 2073 | int len = (int) strlen(s); 2074 | cgiWriteInt(out, len); 2075 | if (((int) fwrite(s, 1, len, out)) != len) { 2076 | return 0; 2077 | } 2078 | return 1; 2079 | } 2080 | 2081 | static int cgiWriteInt(FILE *out, int i) { 2082 | if (!fwrite(&i, sizeof(int), 1, out)) { 2083 | return 0; 2084 | } 2085 | return 1; 2086 | } 2087 | 2088 | static int cgiReadString(FILE *out, char **s); 2089 | 2090 | static int cgiReadInt(FILE *out, int *i); 2091 | 2092 | cgiEnvironmentResultType cgiReadEnvironment(char *filename) { 2093 | FILE *in; 2094 | cgiFormEntry *e = 0, *p; 2095 | char *version; 2096 | /* Prevent compiler warnings */ 2097 | cgiEnvironmentResultType result = cgiEnvironmentIO; 2098 | /* Free any existing data first */ 2099 | cgiFreeResources(); 2100 | /* Be sure to open in binary mode */ 2101 | in = fopen(filename, "rb"); 2102 | if (!in) { 2103 | /* Can't access file */ 2104 | return cgiEnvironmentIO; 2105 | } 2106 | if (!cgiReadString(in, &version)) { 2107 | goto error; 2108 | } 2109 | if (strcmp(version, "CGIC" CGIC_VERSION)) { 2110 | /* 2.02: Merezko Oleg */ 2111 | free(version); 2112 | return cgiEnvironmentWrongVersion; 2113 | } 2114 | /* 2.02: Merezko Oleg */ 2115 | free(version); 2116 | if (!cgiReadString(in, &cgiServerSoftware)) { 2117 | goto error; 2118 | } 2119 | if (!cgiReadString(in, &cgiServerName)) { 2120 | goto error; 2121 | } 2122 | if (!cgiReadString(in, &cgiGatewayInterface)) { 2123 | goto error; 2124 | } 2125 | if (!cgiReadString(in, &cgiServerProtocol)) { 2126 | goto error; 2127 | } 2128 | if (!cgiReadString(in, &cgiServerPort)) { 2129 | goto error; 2130 | } 2131 | if (!cgiReadString(in, &cgiRequestMethod)) { 2132 | goto error; 2133 | } 2134 | if (!cgiReadString(in, &cgiPathInfo)) { 2135 | goto error; 2136 | } 2137 | if (!cgiReadString(in, &cgiPathTranslated)) { 2138 | goto error; 2139 | } 2140 | if (!cgiReadString(in, &cgiScriptName)) { 2141 | goto error; 2142 | } 2143 | if (!cgiReadString(in, &cgiQueryString)) { 2144 | goto error; 2145 | } 2146 | if (!cgiReadString(in, &cgiRemoteHost)) { 2147 | goto error; 2148 | } 2149 | if (!cgiReadString(in, &cgiRemoteAddr)) { 2150 | goto error; 2151 | } 2152 | if (!cgiReadString(in, &cgiAuthType)) { 2153 | goto error; 2154 | } 2155 | if (!cgiReadString(in, &cgiRemoteUser)) { 2156 | goto error; 2157 | } 2158 | if (!cgiReadString(in, &cgiRemoteIdent)) { 2159 | goto error; 2160 | } 2161 | if (!cgiReadString(in, &cgiContentType)) { 2162 | goto error; 2163 | } 2164 | if (!cgiReadString(in, &cgiAccept)) { 2165 | goto error; 2166 | } 2167 | if (!cgiReadString(in, &cgiUserAgent)) { 2168 | goto error; 2169 | } 2170 | if (!cgiReadString(in, &cgiReferrer)) { 2171 | goto error; 2172 | } 2173 | /* 2.0 */ 2174 | if (!cgiReadString(in, &cgiCookie)) { 2175 | goto error; 2176 | } 2177 | if (!cgiReadInt(in, &cgiContentLength)) { 2178 | goto error; 2179 | } 2180 | p = 0; 2181 | while (1) { 2182 | int fileFlag; 2183 | e = (cgiFormEntry *) calloc(1, sizeof(cgiFormEntry)); 2184 | if (!e) { 2185 | cgiFreeResources(); 2186 | fclose(in); 2187 | return cgiEnvironmentMemory; 2188 | } 2189 | memset(e, 0, sizeof(cgiFormEntry)); 2190 | if (!cgiReadString(in, &e->attr)) { 2191 | /* This means we've reached the end of the list. */ 2192 | /* 2.02: thanks to Merezko Oleg */ 2193 | free(e); 2194 | break; 2195 | } 2196 | if (!cgiReadString(in, &e->value)) { 2197 | goto outOfMemory; 2198 | } 2199 | if (!cgiReadString(in, &e->fileName)) { 2200 | goto outOfMemory; 2201 | } 2202 | if (!cgiReadString(in, &e->contentType)) { 2203 | goto outOfMemory; 2204 | } 2205 | if (!cgiReadInt(in, &e->valueLength)) { 2206 | goto outOfMemory; 2207 | } 2208 | if (!cgiReadInt(in, &fileFlag)) { 2209 | goto outOfMemory; 2210 | } 2211 | if (fileFlag) { 2212 | char buffer[1024]; 2213 | FILE *out; 2214 | char tfileName[1024]; 2215 | int got; 2216 | int len = e->valueLength; 2217 | if (getTempFileName(tfileName) 2218 | != cgiParseSuccess) 2219 | { 2220 | result = cgiEnvironmentIO; 2221 | goto error; 2222 | } 2223 | out = fopen(tfileName, "w+b"); 2224 | if (!out) { 2225 | result = cgiEnvironmentIO; 2226 | unlink(tfileName); 2227 | goto error; 2228 | } 2229 | while (len > 0) { 2230 | /* 2.01: try is a bad variable name in 2231 | C++, and it wasn't being used 2232 | properly either */ 2233 | int tryr = len; 2234 | if (tryr > ((int) sizeof(buffer))) { 2235 | tryr = sizeof(buffer); 2236 | } 2237 | got = fread(buffer, 1, tryr, in); 2238 | if (got <= 0) { 2239 | result = cgiEnvironmentIO; 2240 | fclose(out); 2241 | unlink(tfileName); 2242 | goto error; 2243 | } 2244 | if (((int) fwrite(buffer, 1, got, out)) != got) { 2245 | result = cgiEnvironmentIO; 2246 | fclose(out); 2247 | unlink(tfileName); 2248 | goto error; 2249 | } 2250 | len -= got; 2251 | } 2252 | /* cgic 2.05: should be fclose not rewind */ 2253 | fclose(out); 2254 | e->tfileName = (char *) malloc((int) strlen(tfileName) + 1); 2255 | if (!e->tfileName) { 2256 | result = cgiEnvironmentMemory; 2257 | unlink(tfileName); 2258 | goto error; 2259 | } 2260 | strcpy(e->tfileName, tfileName); 2261 | } else { 2262 | e->tfileName = (char *) malloc(1); 2263 | if (!e->tfileName) { 2264 | result = cgiEnvironmentMemory; 2265 | goto error; 2266 | } 2267 | e->tfileName[0] = '\0'; 2268 | } 2269 | e->next = 0; 2270 | if (p) { 2271 | p->next = e; 2272 | } else { 2273 | cgiFormEntryFirst = e; 2274 | } 2275 | p = e; 2276 | } 2277 | fclose(in); 2278 | cgiRestored = 1; 2279 | return cgiEnvironmentSuccess; 2280 | outOfMemory: 2281 | result = cgiEnvironmentMemory; 2282 | error: 2283 | cgiFreeResources(); 2284 | fclose(in); 2285 | if (e) { 2286 | if (e->attr) { 2287 | free(e->attr); 2288 | } 2289 | if (e->value) { 2290 | free(e->value); 2291 | } 2292 | if (e->fileName) { 2293 | free(e->fileName); 2294 | } 2295 | if (e->contentType) { 2296 | free(e->contentType); 2297 | } 2298 | if (e->tfileName) { 2299 | free(e->tfileName); 2300 | } 2301 | free(e); 2302 | } 2303 | return result; 2304 | } 2305 | 2306 | static int cgiReadString(FILE *in, char **s) { 2307 | int len; 2308 | /* 2.0 fix: test cgiReadInt for failure! */ 2309 | if (!cgiReadInt(in, &len)) { 2310 | return 0; 2311 | } 2312 | *s = (char *) malloc(len + 1); 2313 | if (!(*s)) { 2314 | return 0; 2315 | } 2316 | if (((int) fread(*s, 1, len, in)) != len) { 2317 | return 0; 2318 | } 2319 | (*s)[len] = '\0'; 2320 | return 1; 2321 | } 2322 | 2323 | static int cgiReadInt(FILE *out, int *i) { 2324 | if (!fread(i, sizeof(int), 1, out)) { 2325 | return 0; 2326 | } 2327 | return 1; 2328 | } 2329 | 2330 | static int cgiStrEqNc(char *s1, char *s2) { 2331 | while(1) { 2332 | if (!(*s1)) { 2333 | if (!(*s2)) { 2334 | return 1; 2335 | } else { 2336 | return 0; 2337 | } 2338 | } else if (!(*s2)) { 2339 | return 0; 2340 | } 2341 | if (isalpha(*s1)) { 2342 | if (tolower(*s1) != tolower(*s2)) { 2343 | return 0; 2344 | } 2345 | } else if ((*s1) != (*s2)) { 2346 | return 0; 2347 | } 2348 | s1++; 2349 | s2++; 2350 | } 2351 | } 2352 | 2353 | static int cgiStrBeginsNc(char *s1, char *s2) { 2354 | while(1) { 2355 | if (!(*s2)) { 2356 | return 1; 2357 | } else if (!(*s1)) { 2358 | return 0; 2359 | } 2360 | if (isalpha(*s1)) { 2361 | if (tolower(*s1) != tolower(*s2)) { 2362 | return 0; 2363 | } 2364 | } else if ((*s1) != (*s2)) { 2365 | return 0; 2366 | } 2367 | s1++; 2368 | s2++; 2369 | } 2370 | } 2371 | 2372 | static char *cgiFindTarget = 0; 2373 | static cgiFormEntry *cgiFindPos = 0; 2374 | 2375 | static cgiFormEntry *cgiFormEntryFindFirst(char *name) { 2376 | cgiFindTarget = name; 2377 | cgiFindPos = cgiFormEntryFirst; 2378 | return cgiFormEntryFindNext(); 2379 | } 2380 | 2381 | static cgiFormEntry *cgiFormEntryFindNext() { 2382 | while (cgiFindPos) { 2383 | cgiFormEntry *c = cgiFindPos; 2384 | cgiFindPos = c->next; 2385 | 2386 | if (!strcmp(c -> attr, cgiFindTarget)) { 2387 | return c; 2388 | } 2389 | } 2390 | return 0; 2391 | } 2392 | 2393 | static int cgiFirstNonspaceChar(char *s) { 2394 | int len = strspn(s, " \n\r\t"); 2395 | return s[len]; 2396 | } 2397 | 2398 | void cgiStringArrayFree(char **stringArray) { 2399 | char *p; 2400 | char **arrayItself = stringArray; 2401 | p = *stringArray; 2402 | while (p) { 2403 | free(p); 2404 | stringArray++; 2405 | p = *stringArray; 2406 | } 2407 | /* 2.0: free the array itself! */ 2408 | free(arrayItself); 2409 | } 2410 | 2411 | cgiFormResultType cgiCookies(char ***result) { 2412 | char **stringArray; 2413 | int i; 2414 | int total = 0; 2415 | char *p; 2416 | char *n; 2417 | p = cgiCookie; 2418 | while (*p) { 2419 | if (*p == '=') { 2420 | total++; 2421 | } 2422 | p++; 2423 | } 2424 | stringArray = (char **) malloc(sizeof(char *) * (total + 1)); 2425 | if (!stringArray) { 2426 | *result = 0; 2427 | return cgiFormMemory; 2428 | } 2429 | /* initialize all entries to null; the last will stay that way */ 2430 | for (i=0; (i <= total); i++) { 2431 | stringArray[i] = 0; 2432 | } 2433 | i = 0; 2434 | p = cgiCookie; 2435 | while (*p) { 2436 | while (*p && isspace(*p)) { 2437 | p++; 2438 | } 2439 | n = p; 2440 | while (*p && (*p != '=')) { 2441 | p++; 2442 | } 2443 | if (p != n) { 2444 | stringArray[i] = (char *) malloc((p - n) + 1); 2445 | if (!stringArray[i]) { 2446 | cgiStringArrayFree(stringArray); 2447 | *result = 0; 2448 | return cgiFormMemory; 2449 | } 2450 | memcpy(stringArray[i], n, p - n); 2451 | stringArray[i][p - n] = '\0'; 2452 | i++; 2453 | } 2454 | while (*p && (*p != ';')) { 2455 | p++; 2456 | } 2457 | if (!*p) { 2458 | break; 2459 | } 2460 | if (*p == ';') { 2461 | p++; 2462 | } 2463 | } 2464 | *result = stringArray; 2465 | return cgiFormSuccess; 2466 | } 2467 | 2468 | cgiFormResultType cgiFormEntries(char ***result) { 2469 | char **stringArray; 2470 | cgiFormEntry *e, *pe; 2471 | int i; 2472 | int total = 0; 2473 | e = cgiFormEntryFirst; 2474 | while (e) { 2475 | /* Don't count a field name more than once if 2476 | multiple values happen to be present for it */ 2477 | pe = cgiFormEntryFirst; 2478 | while (pe != e) { 2479 | if (!strcmp(e->attr, pe->attr)) { 2480 | goto skipSecondValue; 2481 | } 2482 | pe = pe->next; 2483 | } 2484 | total++; 2485 | skipSecondValue: 2486 | e = e->next; 2487 | } 2488 | stringArray = (char **) malloc(sizeof(char *) * (total + 1)); 2489 | if (!stringArray) { 2490 | *result = 0; 2491 | return cgiFormMemory; 2492 | } 2493 | /* initialize all entries to null; the last will stay that way */ 2494 | for (i=0; (i <= total); i++) { 2495 | stringArray[i] = 0; 2496 | } 2497 | /* Now go get the entries */ 2498 | e = cgiFormEntryFirst; 2499 | i = 0; 2500 | while (e) { 2501 | size_t space; 2502 | /* Don't return a field name more than once if 2503 | multiple values happen to be present for it */ 2504 | pe = cgiFormEntryFirst; 2505 | while (pe != e) { 2506 | if (!strcmp(e->attr, pe->attr)) { 2507 | goto skipSecondValue2; 2508 | } 2509 | pe = pe->next; 2510 | } 2511 | space = strlen(e->attr) + 1; 2512 | stringArray[i] = (char *) malloc(space); 2513 | if (stringArray[i] == 0) { 2514 | /* Memory problems */ 2515 | cgiStringArrayFree(stringArray); 2516 | *result = 0; 2517 | return cgiFormMemory; 2518 | } 2519 | strcpy(stringArray[i], e->attr); 2520 | i++; 2521 | skipSecondValue2: 2522 | e = e->next; 2523 | } 2524 | *result = stringArray; 2525 | return cgiFormSuccess; 2526 | } 2527 | 2528 | #define TRYPUTC(ch) \ 2529 | { \ 2530 | if (putc((ch), cgiOut) == EOF) { \ 2531 | return cgiFormIO; \ 2532 | } \ 2533 | } 2534 | 2535 | cgiFormResultType cgiHtmlEscapeData(const char *data, int len) 2536 | { 2537 | while (len--) { 2538 | if (*data == '<') { 2539 | TRYPUTC('&'); 2540 | TRYPUTC('l'); 2541 | TRYPUTC('t'); 2542 | TRYPUTC(';'); 2543 | } else if (*data == '&') { 2544 | TRYPUTC('&'); 2545 | TRYPUTC('a'); 2546 | TRYPUTC('m'); 2547 | TRYPUTC('p'); 2548 | TRYPUTC(';'); 2549 | } else if (*data == '>') { 2550 | TRYPUTC('&'); 2551 | TRYPUTC('g'); 2552 | TRYPUTC('t'); 2553 | TRYPUTC(';'); 2554 | } else { 2555 | TRYPUTC(*data); 2556 | } 2557 | data++; 2558 | } 2559 | return cgiFormSuccess; 2560 | } 2561 | 2562 | cgiFormResultType cgiHtmlEscape(const char *s) 2563 | { 2564 | return cgiHtmlEscapeData(s, (int) strlen(s)); 2565 | } 2566 | 2567 | /* Output data with the " character HTML-escaped, and no 2568 | other characters escaped. This is useful when outputting 2569 | the contents of a tag attribute such as 'href' or 'src'. 2570 | 'data' is not null-terminated; 'len' is the number of 2571 | bytes in 'data'. Returns cgiFormIO in the event 2572 | of error, cgiFormSuccess otherwise. */ 2573 | cgiFormResultType cgiValueEscapeData(const char *data, int len) 2574 | { 2575 | while (len--) { 2576 | if (*data == '\"') { 2577 | TRYPUTC('&'); 2578 | TRYPUTC('#'); 2579 | TRYPUTC('3'); 2580 | TRYPUTC('4'); 2581 | TRYPUTC(';'); 2582 | } else { 2583 | TRYPUTC(*data); 2584 | } 2585 | data++; 2586 | } 2587 | return cgiFormSuccess; 2588 | } 2589 | 2590 | cgiFormResultType cgiValueEscape(const char *s) 2591 | { 2592 | return cgiValueEscapeData(s, (int) strlen(s)); 2593 | } 2594 | 2595 | 2596 | #ifdef UNIT_TEST 2597 | 2598 | static void unitTestAssert(const int value, const char *message); 2599 | 2600 | static int unitTest() { 2601 | char *input = "one=1&two=2&empty1&four=4&empty2"; 2602 | cgiFormEntry *e; 2603 | cgiParseResultType result = cgiParseFormInput(input, strlen(input)); 2604 | unitTestAssert(result == cgiParseSuccess, "cgiParseFormInput did not return cgiParseSuccess"); 2605 | e = cgiFormEntryFirst; 2606 | unitTestAssert(!!e, "first entry missing"); 2607 | unitTestAssert(!strcmp(e->attr, "one"), "first entry name is not one"); 2608 | unitTestAssert(!strcmp(e->value, "1"), "first entry value is not 1"); 2609 | e = e->next; 2610 | unitTestAssert(!!e, "Test failed: second entry missing"); 2611 | unitTestAssert(!strcmp(e->attr, "two"), "second entry name is not two"); 2612 | unitTestAssert(!strcmp(e->value, "2"), "second entry value is not 2"); 2613 | e = e->next; 2614 | unitTestAssert(!!e, "Test failed: third entry missing"); 2615 | unitTestAssert(!strcmp(e->attr, "empty1"), "third entry name is not empty1"); 2616 | unitTestAssert(!strcmp(e->value, ""), "third entry value is not empty string"); 2617 | e = e->next; 2618 | unitTestAssert(!!e, "Test failed: fourth entry missing"); 2619 | unitTestAssert(!strcmp(e->attr, "four"), "fourth entry name is not four"); 2620 | unitTestAssert(!strcmp(e->value, "4"), "fourth entry value is not 4"); 2621 | e = e->next; 2622 | unitTestAssert(!!e, "Test failed: fifth entry missing"); 2623 | unitTestAssert(!strcmp(e->attr, "empty2"), "fifth entry name is not empty2"); 2624 | unitTestAssert(!strcmp(e->value, ""), "fifth entry value is not empty string"); 2625 | unitTestAssert(!e->next, "unexpected entry at end of list"); 2626 | return 0; 2627 | } 2628 | 2629 | static void unitTestAssert(const int value, const char *message) 2630 | { 2631 | if (value) { 2632 | return; 2633 | } 2634 | fprintf(stderr, "Test failed: %s\n", message); 2635 | exit(1); 2636 | } 2637 | 2638 | 2639 | 2640 | #endif 2641 | -------------------------------------------------------------------------------- /login/cgic.h: -------------------------------------------------------------------------------- 1 | /* The CGI_C library, by Thomas Boutell, version 2.01. CGI_C is intended 2 | to be a high-quality API to simplify CGI programming tasks. */ 3 | 4 | /* Make sure this is only included once. */ 5 | 6 | #ifndef CGI_C 7 | #define CGI_C 1 8 | 9 | /* Bring in standard I/O since some of the functions refer to 10 | types defined by it, such as FILE *. */ 11 | 12 | #include 13 | 14 | /* The various CGI environment variables. Instead of using getenv(), 15 | the programmer should refer to these, which are always 16 | valid null-terminated strings (they may be empty, but they 17 | will never be null). If these variables are used instead 18 | of calling getenv(), then it will be possible to save 19 | and restore CGI environments, which is highly convenient 20 | for debugging. */ 21 | 22 | extern char *cgiServerSoftware; 23 | extern char *cgiServerName; 24 | extern char *cgiGatewayInterface; 25 | extern char *cgiServerProtocol; 26 | extern char *cgiServerPort; 27 | extern char *cgiRequestMethod; 28 | extern char *cgiPathInfo; 29 | extern char *cgiPathTranslated; 30 | extern char *cgiScriptName; 31 | extern char *cgiQueryString; 32 | extern char *cgiRemoteHost; 33 | extern char *cgiRemoteAddr; 34 | extern char *cgiAuthType; 35 | extern char *cgiRemoteUser; 36 | extern char *cgiRemoteIdent; 37 | extern char *cgiContentType; 38 | extern char *cgiAccept; 39 | extern char *cgiUserAgent; 40 | extern char *cgiReferrer; 41 | 42 | /* Cookies as sent to the server. You can also get them 43 | individually, or as a string array; see the documentation. */ 44 | extern char *cgiCookie; 45 | 46 | /* A macro providing the same incorrect spelling that is 47 | found in the HTTP/CGI specifications */ 48 | #define cgiReferer cgiReferrer 49 | 50 | /* The number of bytes of data received. 51 | Note that if the submission is a form submission 52 | the library will read and parse all the information 53 | directly from cgiIn; the programmer need not do so. */ 54 | 55 | extern int cgiContentLength; 56 | 57 | /* Pointer to CGI output. The cgiHeader functions should be used 58 | first to output the mime headers; the output HTML 59 | page, GIF image or other web document should then be written 60 | to cgiOut by the programmer. In the standard CGIC library, 61 | cgiOut is always equivalent to stdout. */ 62 | 63 | extern FILE *cgiOut; 64 | 65 | /* Pointer to CGI input. The programmer does not read from this. 66 | We have continued to export it for backwards compatibility 67 | so that cgic 1.x applications link properly. */ 68 | 69 | extern FILE *cgiIn; 70 | 71 | /* Possible return codes from the cgiForm family of functions (see below). */ 72 | 73 | typedef enum { 74 | cgiFormSuccess, 75 | cgiFormTruncated, 76 | cgiFormBadType, 77 | cgiFormEmpty, 78 | cgiFormNotFound, 79 | cgiFormConstrained, 80 | cgiFormNoSuchChoice, 81 | cgiFormMemory, 82 | cgiFormNoFileName, 83 | cgiFormNoContentType, 84 | cgiFormNotAFile, 85 | cgiFormOpenFailed, 86 | cgiFormIO, 87 | cgiFormEOF 88 | } cgiFormResultType; 89 | 90 | /* These functions are used to retrieve form data. See 91 | cgic.html for documentation. */ 92 | 93 | extern cgiFormResultType cgiFormString( 94 | char *name, char *result, int max); 95 | 96 | extern cgiFormResultType cgiFormStringNoNewlines( 97 | char *name, char *result, int max); 98 | 99 | 100 | extern cgiFormResultType cgiFormStringSpaceNeeded( 101 | char *name, int *length); 102 | 103 | 104 | extern cgiFormResultType cgiFormStringMultiple( 105 | char *name, char ***ptrToStringArray); 106 | 107 | extern void cgiStringArrayFree(char **stringArray); 108 | 109 | extern cgiFormResultType cgiFormInteger( 110 | char *name, int *result, int defaultV); 111 | 112 | extern cgiFormResultType cgiFormIntegerBounded( 113 | char *name, int *result, int min, int max, int defaultV); 114 | 115 | extern cgiFormResultType cgiFormDouble( 116 | char *name, double *result, double defaultV); 117 | 118 | extern cgiFormResultType cgiFormDoubleBounded( 119 | char *name, double *result, double min, double max, double defaultV); 120 | 121 | extern cgiFormResultType cgiFormSelectSingle( 122 | char *name, char choicesText[][20], int choicesTotal, 123 | int *result, int defaultV); 124 | 125 | 126 | extern cgiFormResultType cgiFormSelectMultiple( 127 | char *name, char **choicesText, int choicesTotal, 128 | int *result, int *invalid); 129 | 130 | /* Just an alias; users have asked for this */ 131 | #define cgiFormSubmitClicked cgiFormCheckboxSingle 132 | 133 | extern cgiFormResultType cgiFormCheckboxSingle( 134 | char *name); 135 | 136 | extern cgiFormResultType cgiFormCheckboxMultiple( 137 | char *name, char **valuesText, int valuesTotal, 138 | int *result, int *invalid); 139 | 140 | extern cgiFormResultType cgiFormRadio( 141 | char *name, char **valuesText, int valuesTotal, 142 | int *result, int defaultV); 143 | 144 | /* The paths returned by this function are the original names of files 145 | as reported by the uploading web browser and shoult NOT be 146 | blindly assumed to be "safe" names for server-side use! */ 147 | extern cgiFormResultType cgiFormFileName( 148 | char *name, char *result, int max); 149 | 150 | /* The content type of the uploaded file, as reported by the browser. 151 | It should NOT be assumed that browsers will never falsify 152 | such information. */ 153 | extern cgiFormResultType cgiFormFileContentType( 154 | char *name, char *result, int max); 155 | 156 | extern cgiFormResultType cgiFormFileSize( 157 | char *name, int *sizeP); 158 | 159 | typedef struct cgiFileStruct *cgiFilePtr; 160 | 161 | extern cgiFormResultType cgiFormFileOpen( 162 | char *name, cgiFilePtr *cfpp); 163 | 164 | extern cgiFormResultType cgiFormFileRead( 165 | cgiFilePtr cfp, char *buffer, int bufferSize, int *gotP); 166 | 167 | extern cgiFormResultType cgiFormFileClose( 168 | cgiFilePtr cfp); 169 | 170 | extern cgiFormResultType cgiCookieString( 171 | char *name, char *result, int max); 172 | 173 | extern cgiFormResultType cgiCookieInteger( 174 | char *name, int *result, int defaultV); 175 | 176 | cgiFormResultType cgiCookies( 177 | char ***ptrToStringArray); 178 | 179 | /* path can be null or empty in which case a path of / (entire site) is set. 180 | domain can be a single web site; if it is an entire domain, such as 181 | 'boutell.com', it should begin with a dot: '.boutell.com' */ 182 | extern void cgiHeaderCookieSetString(char *name, char *value, 183 | int secondsToLive, char *path, char *domain); 184 | extern void cgiHeaderCookieSetInteger(char *name, int value, 185 | int secondsToLive, char *path, char *domain); 186 | extern void cgiHeaderLocation(char *redirectUrl); 187 | extern void cgiHeaderStatus(int status, char *statusMessage); 188 | extern void cgiHeaderContentType(char *mimeType); 189 | 190 | typedef enum { 191 | cgiEnvironmentIO, 192 | cgiEnvironmentMemory, 193 | cgiEnvironmentSuccess, 194 | cgiEnvironmentWrongVersion 195 | } cgiEnvironmentResultType; 196 | 197 | extern cgiEnvironmentResultType cgiWriteEnvironment(char *filename); 198 | extern cgiEnvironmentResultType cgiReadEnvironment(char *filename); 199 | 200 | extern int cgiMain(); 201 | 202 | extern cgiFormResultType cgiFormEntries( 203 | char ***ptrToStringArray); 204 | 205 | /* Output string with the <, &, and > characters HTML-escaped. 206 | 's' is null-terminated. Returns cgiFormIO in the event 207 | of error, cgiFormSuccess otherwise. */ 208 | cgiFormResultType cgiHtmlEscape(const char *s); 209 | 210 | /* Output data with the <, &, and > characters HTML-escaped. 211 | 'data' is not null-terminated; 'len' is the number of 212 | bytes in 'data'. Returns cgiFormIO in the event 213 | of error, cgiFormSuccess otherwise. */ 214 | cgiFormResultType cgiHtmlEscapeData(const char *data, int len); 215 | 216 | /* Output string with the " character HTML-escaped, and no 217 | other characters escaped. This is useful when outputting 218 | the contents of a tag attribute such as 'href' or 'src'. 219 | 's' is null-terminated. Returns cgiFormIO in the event 220 | of error, cgiFormSuccess otherwise. */ 221 | cgiFormResultType cgiValueEscape(const char *s); 222 | 223 | /* Output data with the " character HTML-escaped, and no 224 | other characters escaped. This is useful when outputting 225 | the contents of a tag attribute such as 'href' or 'src'. 226 | 'data' is not null-terminated; 'len' is the number of 227 | bytes in 'data'. Returns cgiFormIO in the event 228 | of error, cgiFormSuccess otherwise. */ 229 | cgiFormResultType cgiValueEscapeData(const char *data, int len); 230 | 231 | 232 | #endif /* CGI_C */ 233 | 234 | -------------------------------------------------------------------------------- /login/login.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main( int argc, char *argv[] ) 6 | { 7 | 8 | char *UserInput = NULL; // index the user input data. 9 | char *request_method = NULL; //index the html transfer type. 10 | int data_len = 0; // index the input data's length. 11 | 12 | printf("Content-type:text/html;charset=utf-8\n\n"); //response header. 13 | printf("\n"); 14 | 15 | // HTML page header. 16 | printf(""); 17 | printf("%s", ""); 18 | printf(""); 19 | 20 | if( ! getenv("REQUEST_METHOD") ) 21 | { 22 | printf("No client request from user !\n"); 23 | return -1; 24 | } 25 | request_method = getenv("REQUEST_METHOD"); // trans-type. 26 | 27 | // trans-type : GET 28 | if( ! strcmp( request_method, "GET" ) ) 29 | { 30 | if( getenv( "QUERY_STRING" ) ) 31 | { 32 | UserInput = getenv( "QUERY_STRING" ); 33 | } 34 | data_len = strlen( UserInput ); 35 | 36 | if( NULL == UserInput || 0 == data_len ) 37 | { 38 | printf( "There's no input data !\n" ); 39 | return -1; 40 | } 41 | UserInput[data_len] = '\0'; 42 | if(UserInput[7]=='1'&&UserInput[8]=='3'&&UserInput[9]=='5'&&UserInput[10]=='7') 43 | { 44 | printf(""); 45 | } 46 | else 47 | { 48 | printf("key err
\nyou input key is:
\n %s %c",&UserInput[7]); 49 | } 50 | } 51 | printf(""); 52 | fflush( stdout ); 53 | return 0; 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /login/login.cgi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/login/login.cgi -------------------------------------------------------------------------------- /photos/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/background.jpg -------------------------------------------------------------------------------- /photos/checkcode.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/checkcode.bmp -------------------------------------------------------------------------------- /photos/index-footer-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-footer-bg.gif -------------------------------------------------------------------------------- /photos/index-header-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-header-bg.gif -------------------------------------------------------------------------------- /photos/index-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-logo.gif -------------------------------------------------------------------------------- /photos/index-logout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-logout.png -------------------------------------------------------------------------------- /photos/index-menu-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-menu-bg.gif -------------------------------------------------------------------------------- /photos/index-menu-bg2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-menu-bg2.gif -------------------------------------------------------------------------------- /photos/index-menu-title.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-menu-title.gif -------------------------------------------------------------------------------- /photos/index-menu-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-menu-title.png -------------------------------------------------------------------------------- /photos/index-nav-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-nav-bg.png -------------------------------------------------------------------------------- /photos/index-nav-firstbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-nav-firstbg.png -------------------------------------------------------------------------------- /photos/index-nav-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-nav-left.png -------------------------------------------------------------------------------- /photos/index-nav-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-nav-right.png -------------------------------------------------------------------------------- /photos/index-submenu-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-submenu-bg.gif -------------------------------------------------------------------------------- /photos/index-subnav-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-subnav-bg.gif -------------------------------------------------------------------------------- /photos/index-subnav-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-subnav-left.gif -------------------------------------------------------------------------------- /photos/index-subnav-right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/index-subnav-right.gif -------------------------------------------------------------------------------- /photos/login-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/login-bg.gif -------------------------------------------------------------------------------- /photos/login-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/login-bg.png -------------------------------------------------------------------------------- /photos/login-btn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/login-btn.gif -------------------------------------------------------------------------------- /photos/login-input.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/login-input.gif -------------------------------------------------------------------------------- /photos/login.css: -------------------------------------------------------------------------------- 1 | /*@import "menu.css";*/ 2 | /** 清除内外边距 **/ 3 | body, h1, h2, h3, h4, h5, h6, hr, p, 4 | blockquote, /* structural elements 结构元素 */ 5 | dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ 6 | pre, /* text formatting elements 文本格式元素 */ 7 | form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */ 8 | th, td, /* table elements 表格元素 */ 9 | img/* img elements 图片元素 */{ 10 | border:medium none; 11 | margin: 0; 12 | padding: 0; 13 | } 14 | /** 设置默认字体 **/ 15 | body,button, input, select, textarea { 16 | font: 12px/1.5 '宋体',tahoma, Srial, helvetica, sans-serif; } 17 | body{background:url(background.jpg) no-repeat center;background-size:100% 100%;} 18 | body,html{width:100%;height:100%;} 19 | h1, h2, h3, h4, h5, h6 { font-size: 100%; } 20 | #h1{position:absolute;top:200px;left:280px;} 21 | em{font-style:normal;} 22 | /** 重置列表元素 **/ 23 | ul, ol { list-style: none; } 24 | /** 重置超链接元素 **/ 25 | a { text-decoration: none; color:#000;} 26 | a:hover { text-decoration: underline; color:#0; } 27 | /** 重置图片元素 **/ 28 | img{ border:0px;} 29 | /** 重置表格元素 **/ 30 | table { border-collapse: collapse; border-spacing: 0; } 31 | 32 | /*清除浮动*/ 33 | .clear{ 34 | height:0px; 35 | line-height:0px; 36 | font-size:0px; 37 | clear:both; 38 | } 39 | 40 | /*body{ background:#0a76b0}*/ 41 | #wrap{ 42 | width:960px; 43 | /*margin:0 auto;*/ 44 | /*background:url(login-bg.gif);*/ 45 | height:613px; 46 | text-align: center 47 | 48 | } 49 | #header{ height:170px;} 50 | #content-wrap{ width:593px; height:357px; background:url(login-bg.png); 51 | position:absolute;top:250px;left:140px;} 52 | .content{ width:210px; height:237px; margin:0 auto;} 53 | .space{ height:103px;} 54 | .login-btn{ width:68px; height:28px; background:url(login-btn.gif) -6px -6px;} 55 | .login-btn:hover{ background-position:-6px -49px;} 56 | .field{ height:50px;} 57 | .field label{ color:#dbf2ff} 58 | .btn{text-align:center;} 59 | .field input{ background:url(login-input.gif); width:159px; height:29px; line-height:29px; text-indent:35px;} 60 | .field .password{ 61 | background-position:0 -29px; 62 | } 63 | .field .yangzheng { 64 | background-position:0 -58px; 65 | width: 80px; 66 | text-align: left; 67 | } 68 | -------------------------------------------------------------------------------- /photos/page-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/page-bg.gif -------------------------------------------------------------------------------- /photos/page-pageTitle-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/page-pageTitle-bg.gif -------------------------------------------------------------------------------- /photos/page-thead-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/page-thead-bg.gif -------------------------------------------------------------------------------- /photos/sidebar-on.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/photos/sidebar-on.gif -------------------------------------------------------------------------------- /photos/style.css: -------------------------------------------------------------------------------- 1 | /*@import "menu.css";*/ 2 | /** 清除内外边距 *Download by http://www.codesc.net*/ 3 | body, h1, h2, h3, h4, h5, h6, hr, p, 4 | blockquote, /* structural elements 结构元素 */ 5 | dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ 6 | pre, /* text formatting elements 文本格式元素 */ 7 | form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */ 8 | th, td, /* table elements 表格元素 */ 9 | img/* img elements 图片元素 */{ 10 | margin: 0; 11 | padding: 0; 12 | } 13 | /** 设置默认字体 **/ 14 | body,button, input, select, textarea { 15 | font: 12px/1.5 '宋体',tahoma, Srial, helvetica, sans-serif; } 16 | h1, h2, h3, h4, h5, h6 { font-size: 100%; } 17 | em{font-style:normal;} 18 | /** 重置列表元素 **/ 19 | ul, ol { list-style: none; } 20 | /** 重置超链接元素 **/ 21 | a { text-decoration: none; color:#000;} 22 | a:hover { text-decoration: underline; color:#3363a7; } 23 | /** 重置图片元素 **/ 24 | img{ border:0px;} 25 | /** 重置表格元素 **/ 26 | table { border-collapse: collapse; border-spacing: 0; } 27 | 28 | /*清除浮动*/ 29 | .clear{ 30 | height:0px; 31 | line-height:0px; 32 | font-size:0px; 33 | clear:both; 34 | } 35 | .fleft{ float:left} 36 | .fright{ float:right} 37 | #wrap{ width:100%;} 38 | #header{ height:78px; background:url(index-header-bg.gif) repeat-x;} 39 | .logo{ width:362px; height:51px; background:url(index-logo.gif);} 40 | .header-rt { 41 | margin-top: 20px; 42 | margin-left: 100px; 43 | overflow: hidden; 44 | color: #FFFFFF; 45 | text-align: right; 46 | margin-right: 60px; 47 | } 48 | 49 | .logout{ width:23px; height:24px; background:url(index-logout.png); margin-top:14px;} 50 | .nav ul{ height:51px; overflow:hidden; color:#effaff} 51 | .nav li{ float:left; padding-top:27px; width:93px; height:51px; background:url(index-nav-bg.png); text-align:center;} 52 | .nav li:hover{ background-position:0 -52px;} 53 | .nav .first{ background:url(index-nav-firstbg.png);} 54 | .nav .first:hover{ background-position:0 -52px;} 55 | 56 | .nav-left{ width:34px; height:51px; background:url(index-nav-left.png);} 57 | .nav-right{ width:34px; height:51px; background:url(index-nav-right.png);} 58 | .subnav{ height:27px; background:url(index-subnav-bg.gif)} 59 | .subnav .subnavLeft{ width:17px; height:27px; background:url(index-subnav-left.gif)} 60 | .subnav .subnavRight{ width:17px; height:27px; background:url(index-subnav-right.gif)} 61 | .menu{ width:168px; height:495px; background:#e6f4fa; color:#075587; margin-left:5px;} 62 | .menu ul{ width:168px;} 63 | .menu ul li{ width:168px; background:url(index-menu-bg.gif) no-repeat; text-align:center} 64 | .menu ul li a{ height:26px; line-height:26px; color:#075587} 65 | .menu ul li a:hover{ height:26px; line-height:26px; color:#075587; text-decoration:none; margin-left:10px;} 66 | .menu .subMenuTitle{ background:url(index-menu-title.gif); text-align:center; height:27px; line-height:26px; color:#fff} 67 | .menu ul li ul{ 68 | width:168px; 69 | } 70 | .menu ul li ul li{ background:url(index-submenu-bg.gif);} 71 | 72 | 73 | 74 | .sidebar{ 75 | width:5px; 76 | height:500px; 77 | background-color: #198BC9; 78 | } 79 | .sidebar .btn{ width:5px; height:39px; background:url(sidebar-on.gif); margin-top:200px;} 80 | .sidebar .btn:hover{ background-position:0 -39px;} 81 | .page{ width:auto; height:500px; background:#198bc9} 82 | .page iframe{ margin:0 auto;} 83 | #content .space{ height:5px; font-size:0px; background:#198bc9} 84 | #footer{ width:100%; height:26px; line-height:26px; background:url(index-footer-bg.gif);} 85 | 86 | 87 | .pageTitle{ height:27px; line-height:27px; color:#075587; background:url(page-pageTitle-bg.gif); } 88 | .pageTitle span{ margin-left:10px;} 89 | .pageButton{ 90 | height:auto; 91 | text-indent: 20px; 92 | } 93 | 94 | 95 | .pageColumn{ background:url(page-bg.gif) repeat-x; padding:5px;} 96 | .pageColumn table{ 97 | width:100% 98 | } 99 | .pageColumn thead{ border:1px solid #bfd8e0; color:#075587; background:url(page-thead-bg.gif);} 100 | .pageColumn thead th{ border-left:1px solid #c5dbe2; text-align:center; height:28px;} 101 | .pageColumn tbody tr{ border:1px solid #bfd8e0; height:28px;} 102 | .pageColumn tbody .trLight{ background:#f9fcfd} 103 | .pageColumn tbody .checkBox{ background:#f1f7f9; border:1px solid #bfd8e0; text-align:center} 104 | .pageColumn tbody td{ text-align:center;} 105 | /* .pageColumn */ 106 | .hidden { 107 | display: none; 108 | } 109 | .display { 110 | display: block; 111 | } 112 | #wrap #content { 113 | background-color: #198BC9; 114 | } 115 | .biaoge tbody td { text-align:left;} 116 | .biaoge td { height:30px; line-height:30px;} 117 | .text { width:160px; height:18px; border:1px solid #999;} 118 | .text1{ width:300px; height:18px; border:1px solid #999;} 119 | .text2{ width:300px; height:80px; border:1px solid #999;} 120 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/readme.txt -------------------------------------------------------------------------------- /waterconfig.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingfuyi/cgic/0c9f626f0c99ae072c8b260e03823adb6f99a6fd/waterconfig.c -------------------------------------------------------------------------------- /watersys.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 适配器配置 8 | 110 | 111 | 112 | 113 |
114 |
115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 |
水系统配置
通道号信号类型量程(Pa/m/℃)下限报警阈值上限报警阈值采集周期(s)初始值安装位置
1#
2#
3#
4#
5#
6#
7#
8#
9#
10#
11#
12#
13#
14#
15#
16#
409 | 410 | 411 |
412 |
413 | 414 | 415 | 416 | 1153 | 1154 | --------------------------------------------------------------------------------