📄 webhttpd.c
字号:
/* * webhttpd.c * * HTTP Control interface for motion. * * Specs : http://www.lavrsen.dk/twiki/bin/view/Motion/MotionHttpAPI * * Copyright 2004-2005 by Angel Carpintero (ack@telefonica.net) * This software is distributed under the GNU Public License Version 2 * See also the file 'COPYING'. * */#include "webhttpd.h" /* already includes motion.h */#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <stddef.h>#include <stdint.h> pthread_mutex_t httpd_mutex;int warningkill; // This is a dummy variable use to kill warnings when not checking sscanf and similar functionsstatic const char* ini_template = "<html><head><title>Motion "VERSION"</title></head>\n" "<body>\n";static const char *set_template = "<html><head><script language='javascript'>" "function show(){top.location.href=" "'set?'+document.n.onames.options[document.n.onames.selectedIndex].value" "+'='+document.s.valor.value;" "}</script>\n<title>Motion "VERSION"</title>\n" "</head><body>\n";static const char* end_template = "</body>\n" "</html>\n";static const char* ok_response = "HTTP/1.1 200 OK\r\n" "Server: Motion-httpd/"VERSION"\r\n" "Connection: close\r\n" "Max-Age: 0\r\n" "Expires: 0\r\n" "Cache-Control: no-cache\r\n" "Cache-Control: private\r\n" "Pragma: no-cache\r\n" "Content-type: text/html\r\n\r\n";static const char* ok_response_raw = "HTTP/1.1 200 OK\r\n" "Server: Motion-httpd/"VERSION"\r\n" "Connection: close\r\n" "Max-Age: 0\r\n" "Expires: 0\r\n" "Cache-Control: no-cache\r\n" "Cache-Control: private\r\n" "Pragma: no-cache\r\n" "Content-type: text/plain\r\n\r\n";static const char* bad_request_response = "HTTP/1.0 400 Bad Request\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Bad Request</h1>\n" "<p>The server did not understand your request.</p>\n" "</body>\n" "</html>\n";static const char* bad_request_response_raw = "HTTP/1.0 400 Bad Request\r\n" "Content-type: text/plain\r\n\r\n" "Bad Request";static const char* not_found_response_template = "HTTP/1.0 404 Not Found\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Not Found</h1>\n" "<p>The requested URL was not found on the server.</p>\n" "</body>\n" "</html>\n";static const char* not_found_response_template_raw = "HTTP/1.0 404 Not Found\r\n" "Content-type: text/plain\r\n\r\n" "Not Found";static const char* not_found_response_valid = "HTTP/1.0 404 Not Valid\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Not Valid</h1>\n" "<p>The requested URL is not valid.</p>\n" "</body>\n" "</html>\n";static const char* not_found_response_valid_raw = "HTTP/1.0 404 Not Valid\r\n" "Content-type: text/plain\r\n\r\n" "The requested URL is not valid.";static const char* not_valid_syntax = "HTTP/1.0 404 Not Valid Syntax\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Not Valid Syntax</h1>\n" "</body>\n" "</html>\n";static const char* not_valid_syntax_raw = "HTTP/1.0 404 Not Valid Syntax\r\n" "Content-type: text/plain\r\n\r\n" "Not Valid Syntax\n";static const char* not_track = "HTTP/1.0 200 OK\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Tracking Not Enabled</h1>\n";static const char* not_track_raw = "HTTP/1.0 200 OK\r\n" "Content-type: text/plain\r\n\r\n" "Tracking Not Enabled";static const char* track_error = "HTTP/1.0 200 OK\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Track Error</h1>\n";static const char* track_error_raw = "HTTP/1.0 200 OK\r\n" "Content-type: text/plain\r\n\r\n" "Track Error";static const char* error_value = "HTTP/1.0 200 OK\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Value Error</h1>\n";static const char* error_value_raw = "HTTP/1.0 200 OK\r\n" "Content-type: text/plain\r\n\r\n" "Value Error"; static const char* not_found_response_valid_command = "HTTP/1.0 404 Not Valid Command\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Not Valid Command</h1>\n" "<p>The requested URL is not valid Command.</p>\n" "</body>\n" "</html>\n";static const char* not_found_response_valid_command_raw = "HTTP/1.0 404 Not Valid Command\r\n" "Content-type: text/plain\n\n" "Not Valid Command\n";static const char* bad_method_response_template = "HTTP/1.0 501 Method Not Implemented\r\n" "Content-type: text/html\r\n\r\n" "<html>\n" "<body>\n" "<h1>Method Not Implemented</h1>\n" "<p>The method is not implemented by this server.</p>\n" "</body>\n" "</html>\n";static const char* bad_method_response_template_raw = "HTTP/1.0 501 Method Not Implemented\r\n" "Content-type: text/plain\r\n\r\n" "Method Not Implemented\n";static const char *request_auth_response_template= "HTTP/1.0 401 Authorization Required\r\n" "WWW-Authenticate: Basic realm=\"Motion Security Access\"\r\n";static void send_template_ini_client(int client_socket, const char* template){ ssize_t nwrite = 0; nwrite = write(client_socket, ok_response, strlen (ok_response)); nwrite += write(client_socket, template, strlen(template)); if (nwrite != (ssize_t)(strlen(ok_response) + strlen(template))) motion_log(LOG_ERR, 1, "httpd send_template_ini_client");}static void send_template_ini_client_raw(int client_socket){ ssize_t nwrite = 0; nwrite = write(client_socket, ok_response_raw, strlen (ok_response_raw)); if (nwrite != (ssize_t)strlen(ok_response_raw)) motion_log(LOG_ERR, 1, "httpd send_template_ini_client_raw");}static void send_template(int client_socket, char *res){ ssize_t nwrite = 0; nwrite = write(client_socket, res, strlen(res)); if ( nwrite != (ssize_t)strlen(res)) motion_log(LOG_ERR, 1, "httpd send_template failure write");}static void send_template_raw(int client_socket, char *res){ ssize_t nwrite = 0; nwrite = write(client_socket, res, strlen(res));}static void send_template_end_client(int client_socket){ ssize_t nwrite = 0; nwrite = write(client_socket, end_template, strlen(end_template));}static void response_client(int client_socket, const char* template, char *back){ ssize_t nwrite = 0; nwrite = write(client_socket, template, strlen(template)); if (back != NULL) { send_template(client_socket, back); send_template_end_client(client_socket); }}/* * check_authentication * * return 1 on success * return 0 on error */#if 0static unsigned short int check_authentication(char *authentication, char *auth_base64, size_t size_auth, const char *conf_auth){ unsigned short int ret=0; char *userpass = NULL; authentication = (char *) mymalloc(BASE64_LENGTH(size_auth) + 1); userpass = mymalloc(size_auth + 4); /* base64_encode can read 3 bytes after the end of the string, initialize it */ memset(userpass, 0, size_auth + 4); strcpy(userpass, conf_auth); base64_encode(userpass, authentication, size_auth); free(userpass); if (!strcmp(authentication, auth_base64)) ret=1; return ret;}#endifstatic char *replace(const char *str, const char *old, const char *new){ char *ret, *r; const char *p, *q; size_t oldlen = strlen(old); size_t count, retlen, newlen = strlen(new); if (oldlen != newlen) { for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) count++; /* this is undefined if p - str > PTRDIFF_MAX */ retlen = p - str + strlen(p) + count * (newlen - oldlen); } else retlen = strlen(str); ret = malloc(retlen + 1); for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) { /* this is undefined if q - p > PTRDIFF_MAX */ ptrdiff_t l = q - p; memcpy(r, p, l); r += l; memcpy(r, new, newlen); r += newlen; } strcpy(r, p); return ret;} /* This function decode the values from GET request following the http RFC.*/static void url_decode(char *urlencoded, size_t length){ char *data=urlencoded; char *urldecoded=urlencoded; while (length > 0) { if (*data == '%') { char c[3]; int i; data++; length--; c[0] = *data++; length--; c[1] = *data; c[2] = 0; warningkill = sscanf(c, "%x", &i); if (i < 128) *urldecoded++ = (char)i; else { *urldecoded++ = '%'; *urldecoded++ = c[0]; *urldecoded++ = c[1]; } } else if (*data=='+') { *urldecoded++=' '; } else { *urldecoded++=*data; } data++; length--; } *urldecoded = '\0';}/* This function manages/parses the config action for motion ( set , get , write , list ). return 1 to exit from function.*/static unsigned short int config(char *pointer, char *res, unsigned short int length_uri, unsigned short int thread, int client_socket, void *userdata){ char question; char command[256] = {'\0'}; unsigned short int i; struct context **cnt = userdata; warningkill = sscanf (pointer, "%255[a-z]%c", command , &question); if (!strcmp(command,"list")) { pointer = pointer + 4; length_uri = length_uri - 4; if (length_uri == 0) { const char *value = NULL; char *retval = NULL; /*call list*/ if (cnt[0]->conf.control_html_output) { send_template_ini_client(client_socket, ini_template); sprintf(res, "<a href=/%hu/config><– back</a><br><br>\n<b>Thread %hu</b>\n<ul>", thread, thread); send_template(client_socket, res); for (i=0; config_params[i].param_name != NULL; i++) { if ((thread != 0) && (config_params[i].main_thread)) continue; value = config_params[i].print(cnt, NULL, i, thread); if (value == NULL) { retval=NULL; /* Only get the thread value for main thread */ if (thread == 0) config_params[i].print(cnt, &retval, i, thread); /* thread value*/ if (retval) { if (!strcmp(retval,"")) { free(retval); retval = strdup("No threads"); } else { char *temp=retval; size_t retval_miss = 0; size_t retval_len = strlen(retval); unsigned short int ind=0; char thread_strings[1024]={'\0'};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -