📄 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 "motion.h"#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.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></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</head>\n" "<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); }}static int check_authentication(char *authentication, char *auth_base64, size_t size_auth, const char *conf_auth){ 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;}/* This function decode the values from GET request following the http RFC.*/static int url_decode(char *urlencoded, int 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'; return 0;}/* This function manages/parses the config action for motion ( set , get , write , list ).*/static int config(char *pointer, char *res, int length_uri, int thread, int client_socket, void *userdata){ char question; char command[256] = {'\0'}; int i; struct context **cnt = userdata; warningkill = sscanf (pointer, "%256[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=/%d/config><- back</a>", thread); send_template(client_socket, res); for (i=0; config_params[i].param_name != NULL; i++) { 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); int ind=0; char thread_strings[1024]={'\0'}; while (retval_miss != retval_len) { while (*temp != '\n') { thread_strings[ind++] = *temp; retval_miss++; temp++; } temp++; thread_strings[ind++] = '<'; thread_strings[ind++] = 'b'; thread_strings[ind++] = 'r'; thread_strings[ind++] = '>'; retval_miss++; } free(retval); retval = NULL; retval = strdup(thread_strings); } sprintf(res, "<li><a href=/%d/config/set?%s>%s</a> = %s</li>\n", thread, config_params[i].param_name, config_params[i].param_name, retval); free(retval); } else if (thread != 0) { /* get the value from main thread for the rest of threads */ value = config_params[i].print(cnt, NULL, i, 0); sprintf(res,"<li><a href=/%d/config/set?%s>%s</a> = %s</li>\n", thread, config_params[i].param_name, config_params[i].param_name, value ? value : "(not defined)"); } else { sprintf(res, "<li><a href=/%d/config/set?%s>%s</a> = %s</li>\n", thread, config_params[i].param_name, config_params[i].param_name, "(not defined)"); } } else { sprintf(res,"<li><a href=/%d/config/set?%s>%s</a> = %s</li>\n",thread, config_params[i].param_name, config_params[i].param_name, value); } send_template(client_socket, res); } sprintf(res,"<br><a href=/%d/config><- back</a>",thread); send_template(client_socket, res); send_template_end_client(client_socket); } else { send_template_ini_client_raw(client_socket); for (i=0; config_params[i].param_name != NULL; i++) { value=config_params[i].print(cnt, NULL, i, thread); if (value == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -