mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2026-03-14 21:10:11 +01:00
Moved juci ubus module to juci repo
This commit is contained in:
parent
3ea6e0e0e6
commit
eaa6d45037
9 changed files with 0 additions and 4585 deletions
|
|
@ -1,52 +0,0 @@
|
|||
#
|
||||
# Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ubus-mod-juci
|
||||
#PKG_VERSION:=$(shell git --git-dir=$(CURDIR)/../.git log -1 --pretty="%ci %h" | awk '{ print $$1 "-" $$4 }')
|
||||
PKG_VERSION:=15.6.8
|
||||
PKG_MAINTAINER:=Martin K. Schroder <mkschreder.uk@gmail.com>
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Build/Prepare
|
||||
$(INSTALL_DIR) $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Package/ubus-mod-juci
|
||||
SECTION:=ubus-mod-juci
|
||||
CATEGORY:=UBUS
|
||||
TITLE:=UBUS UCI Plugin
|
||||
DEPENDS:=+rpcd +libubox +libubus
|
||||
endef
|
||||
|
||||
define Package/ubus-mod-juci/description
|
||||
Provides support for writing lightweight ubus plugins
|
||||
endef
|
||||
|
||||
define Package/ubus-mod-juci/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/rpcd
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ubus-mod-juci.so $(1)/usr/lib/rpcd/
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(CP) ./access.json $(1)/usr/share/rpcd/acl.d/ubus-mod-juci.json
|
||||
$(INSTALL_DIR) $(1)/usr/libexec $(1)/www/cgi-bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/io/juci-cgi $(1)/usr/libexec/
|
||||
$(LN) /usr/libexec/juci-cgi $(1)/www/cgi-bin/juci-upload
|
||||
$(LN) /usr/libexec/juci-cgi $(1)/www/cgi-bin/juci-backup
|
||||
endef
|
||||
|
||||
define Package/ubus-mod-juci/postinst
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ubus-mod-juci))
|
||||
|
|
@ -1,435 +0,0 @@
|
|||
{
|
||||
"juciguest": {
|
||||
"description": "Functions allowed for non logged-in users",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.ui": [
|
||||
"themes"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"core": {
|
||||
"description": "Core functions for JUCI",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.ui": [
|
||||
"*"
|
||||
],
|
||||
"session": [
|
||||
"access",
|
||||
"destroy"
|
||||
],
|
||||
"uci": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"status": {
|
||||
"description": "Status information display",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"iwinfo": [
|
||||
"devices",
|
||||
"info",
|
||||
"assoclist",
|
||||
"phyname"
|
||||
],
|
||||
"router": [
|
||||
"dslstats",
|
||||
"info",
|
||||
"clients",
|
||||
"igmptable"
|
||||
],
|
||||
"system": [
|
||||
"info",
|
||||
"board"
|
||||
],
|
||||
"network.interface": [
|
||||
"status"
|
||||
],
|
||||
"juci.network": [
|
||||
"conntrack_count",
|
||||
"dhcp_leases",
|
||||
"dhcp6_leases",
|
||||
"arp_table",
|
||||
"routes",
|
||||
"routes6"
|
||||
],
|
||||
"juci.system": [
|
||||
"diskfree",
|
||||
"syslog",
|
||||
"dmesg",
|
||||
"process_list"
|
||||
],
|
||||
"service": [
|
||||
"list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"process_signal"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"system": {
|
||||
"description": "General system settings",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"system": [
|
||||
"info",
|
||||
"board"
|
||||
],
|
||||
"juci.system": [
|
||||
"init_list"
|
||||
]
|
||||
},
|
||||
"uci": [
|
||||
"juci"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"init_action"
|
||||
]
|
||||
},
|
||||
"uci": [
|
||||
"juci"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"admin": {
|
||||
"description": "Authentication and SSH settings",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"sshkeys_get",
|
||||
"upgrade_test",
|
||||
"upgrade_clean",
|
||||
"upgrade_check",
|
||||
"upgrade_start"
|
||||
],
|
||||
"asterisk": [
|
||||
"status"
|
||||
],
|
||||
"asterisk.call_log": [
|
||||
"list",
|
||||
"sshkeys_get"
|
||||
],
|
||||
"wps": [
|
||||
"genpin",
|
||||
"setpin",
|
||||
"pbc",
|
||||
"showpin",
|
||||
"stapin",
|
||||
"status",
|
||||
"stop"
|
||||
],
|
||||
"router": [
|
||||
"networks"
|
||||
],
|
||||
"network.interface": [
|
||||
"dump"
|
||||
]
|
||||
},
|
||||
"uci": [
|
||||
"dropbear",
|
||||
"boardpanel",
|
||||
"hosts",
|
||||
"voice_client",
|
||||
"juci"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"sshkeys_set",
|
||||
"password_set"
|
||||
],
|
||||
"asterisk.call_log": [
|
||||
"list"
|
||||
],
|
||||
"wps": [
|
||||
"genpin",
|
||||
"setpin",
|
||||
"pbc",
|
||||
"showpin",
|
||||
"stapin",
|
||||
"status",
|
||||
"stop"
|
||||
]
|
||||
},
|
||||
"uci": [
|
||||
"dropbear",
|
||||
"boardpanel",
|
||||
"hosts",
|
||||
"voice_client",
|
||||
"juci"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"users": {
|
||||
"description": "Guest login settings",
|
||||
"read": {
|
||||
"uci": [
|
||||
"rpcd"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"uci": [
|
||||
"rpcd"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"software": {
|
||||
"description": "Package management",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"system": [
|
||||
"info",
|
||||
"board"
|
||||
],
|
||||
"juci.opkg": [
|
||||
"list",
|
||||
"list_installed",
|
||||
"find",
|
||||
"config_get"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.opkg": [
|
||||
"install",
|
||||
"remove",
|
||||
"update",
|
||||
"config_set"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"upgrade": {
|
||||
"description": "Firmware upgrade",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"upgrade_test",
|
||||
"reset_test"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"juci-io": [
|
||||
"upload"
|
||||
],
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"upgrade_start",
|
||||
"upgrade_clean",
|
||||
"reset_start",
|
||||
"reboot"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"backup": {
|
||||
"description": "Backup and Restore",
|
||||
"read": {
|
||||
"juci-io": [
|
||||
"backup"
|
||||
],
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"backup_config_get",
|
||||
"backup_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"backup_clean",
|
||||
"backup_config_set",
|
||||
"backup_restore",
|
||||
"reboot"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"startup": {
|
||||
"description": "System boot settings",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"init_list",
|
||||
"rclocal_get"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"init_action",
|
||||
"rclocal_set"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"cron": {
|
||||
"description": "Crontab management",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"crontab_get"
|
||||
]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"juci.system": [
|
||||
"crontab_set"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"leds": {
|
||||
"description": "Hardware LED configuration",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"network.device": [
|
||||
"status"
|
||||
],
|
||||
"juci.system": [
|
||||
"led_list",
|
||||
"usb_list"
|
||||
]
|
||||
},
|
||||
"uci": [
|
||||
"system"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"uci": [
|
||||
"system"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"diagnostics": {
|
||||
"description": "Network diagnostic tools",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"juci.network": [
|
||||
"ping",
|
||||
"ping6",
|
||||
"traceroute",
|
||||
"traceroute6",
|
||||
"nslookup"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"hostnames": {
|
||||
"description": "Host entry management",
|
||||
"read": {
|
||||
"uci": [
|
||||
"dhcp"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"uci": [
|
||||
"dhcp"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"description": "Network, switch and routing configuration",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"network": [
|
||||
"get_proto_handlers"
|
||||
],
|
||||
"network.device": [
|
||||
"status"
|
||||
],
|
||||
"network.interface": [
|
||||
"dump"
|
||||
],
|
||||
"network.wireless": [
|
||||
"status"
|
||||
],
|
||||
"juci.network": [
|
||||
"switch_list",
|
||||
"switch_info",
|
||||
"switch_status",
|
||||
"device_list",
|
||||
"conntrack_table",
|
||||
"dslstats"
|
||||
],
|
||||
"juci.network.bwmon": [
|
||||
"devices",
|
||||
"statistics"
|
||||
],
|
||||
"router": [ "radios" ]
|
||||
},
|
||||
"uci": [
|
||||
"network",
|
||||
"wireless",
|
||||
"broadcom",
|
||||
"ddns"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"uci": [
|
||||
"network",
|
||||
"wireless"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"wireless": {
|
||||
"description": "Wireless configuration",
|
||||
"read": {
|
||||
"uci": [
|
||||
"wireless"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"uci": [
|
||||
"wireless",
|
||||
"ddns"
|
||||
]
|
||||
}
|
||||
},
|
||||
"firewall": {
|
||||
"description": "Firewall configuration",
|
||||
"read": {
|
||||
"uci": [
|
||||
"firewall"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"uci": [
|
||||
"firewall"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
config 'settings' 'settings'
|
||||
option theme 'vodafone'
|
||||
option lang 'en'
|
||||
list themes 'vodaphone'
|
||||
list plugins 'core'
|
||||
list plugins 'internet'
|
||||
list plugins 'phone'
|
||||
list plugins 'settings'
|
||||
list plugins 'status'
|
||||
list plugins 'wifi'
|
||||
list languages 'en'
|
||||
list languages 'se'
|
||||
list languages 'de'
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
PROJECT(ubus-mod-juci C)
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY(io)
|
||||
|
||||
ADD_DEFINITIONS(-Os -Wall -Wno-format-y2k -W -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -Wmissing-field-initializers -Wextra -Wformat=2 -Wno-format-nonliteral -Wpointer-arith -Wno-missing-braces --std=gnu99 -g3 -Wmissing-declarations -Iinclude)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
||||
ADD_LIBRARY(ubus-mod-juci MODULE juci.c)
|
||||
TARGET_LINK_LIBRARIES(ubus-mod-juci ubox ubus )
|
||||
SET_TARGET_PROPERTIES(ubus-mod-juci PROPERTIES OUTPUT_NAME ubus-mod-juci PREFIX "")
|
||||
|
||||
INSTALL(TARGETS ubus-mod-juci LIBRARY DESTINATION lib)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
PROJECT(luciexpress-io C)
|
||||
|
||||
INCLUDE(CheckFunctionExists)
|
||||
|
||||
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -Wmissing-declarations)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
|
||||
IF(APPLE)
|
||||
INCLUDE_DIRECTORIES(/opt/local/include)
|
||||
LINK_DIRECTORIES(/opt/local/lib)
|
||||
ENDIF()
|
||||
|
||||
ADD_EXECUTABLE(juci-cgi main.c multipart_parser.c)
|
||||
TARGET_LINK_LIBRARIES(juci-cgi ubox ubus)
|
||||
|
||||
INSTALL(TARGETS juci-cgi RUNTIME DESTINATION sbin)
|
||||
|
|
@ -1,688 +0,0 @@
|
|||
/*
|
||||
* juci-io - JUCI non-RPC helper
|
||||
*
|
||||
* Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <libubus.h>
|
||||
#include <libubox/blobmsg.h>
|
||||
|
||||
#include "multipart_parser.h"
|
||||
|
||||
|
||||
enum part {
|
||||
PART_UNKNOWN,
|
||||
PART_SESSIONID,
|
||||
PART_FILENAME,
|
||||
PART_FILEMODE,
|
||||
PART_FILEDATA
|
||||
};
|
||||
|
||||
const char *parts[] = {
|
||||
"(bug)",
|
||||
"sessionid",
|
||||
"filename",
|
||||
"filemode",
|
||||
"filedata",
|
||||
};
|
||||
|
||||
struct state
|
||||
{
|
||||
bool is_content_disposition;
|
||||
enum part parttype;
|
||||
char *sessionid;
|
||||
char *filename;
|
||||
bool filedata;
|
||||
int filemode;
|
||||
int filefd;
|
||||
};
|
||||
|
||||
enum {
|
||||
SES_ACCESS,
|
||||
__SES_MAX,
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy ses_policy[__SES_MAX] = {
|
||||
[SES_ACCESS] = { .name = "access", .type = BLOBMSG_TYPE_BOOL },
|
||||
};
|
||||
|
||||
|
||||
static struct state st;
|
||||
|
||||
static void
|
||||
session_access_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *tb[__SES_MAX];
|
||||
bool *allow = (bool *)req->priv;
|
||||
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
blobmsg_parse(ses_policy, __SES_MAX, tb, blob_data(msg), blob_len(msg));
|
||||
|
||||
if (tb[SES_ACCESS])
|
||||
*allow = blobmsg_get_bool(tb[SES_ACCESS]);
|
||||
}
|
||||
|
||||
static bool
|
||||
session_access(const char *sid, const char *obj, const char *func)
|
||||
{
|
||||
uint32_t id;
|
||||
bool allow = false;
|
||||
struct ubus_context *ctx;
|
||||
static struct blob_buf req;
|
||||
|
||||
ctx = ubus_connect(NULL);
|
||||
|
||||
if (!ctx || ubus_lookup_id(ctx, "session", &id))
|
||||
goto out;
|
||||
|
||||
blob_buf_init(&req, 0);
|
||||
blobmsg_add_string(&req, "ubus_rpc_session", sid);
|
||||
blobmsg_add_string(&req, "scope", "juci-io");
|
||||
blobmsg_add_string(&req, "object", obj);
|
||||
blobmsg_add_string(&req, "function", func);
|
||||
|
||||
ubus_invoke(ctx, id, "access", req.head, session_access_cb, &allow, 500);
|
||||
|
||||
out:
|
||||
if (ctx)
|
||||
ubus_free(ctx);
|
||||
|
||||
return allow;
|
||||
}
|
||||
|
||||
static char *
|
||||
md5sum(const char *file)
|
||||
{
|
||||
pid_t pid;
|
||||
int fds[2];
|
||||
static char md5[33];
|
||||
|
||||
if (pipe(fds))
|
||||
return NULL;
|
||||
|
||||
switch ((pid = fork()))
|
||||
{
|
||||
case -1:
|
||||
return NULL;
|
||||
|
||||
case 0:
|
||||
uloop_done();
|
||||
|
||||
dup2(fds[1], 1);
|
||||
|
||||
close(0);
|
||||
close(2);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
if (execl("/bin/busybox", "/bin/busybox", "md5sum", file, NULL));
|
||||
return NULL;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
memset(md5, 0, sizeof(md5));
|
||||
read(fds[0], md5, 32);
|
||||
waitpid(pid, NULL, 0);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
}
|
||||
|
||||
return md5;
|
||||
}
|
||||
|
||||
static char *
|
||||
datadup(const void *in, size_t len)
|
||||
{
|
||||
char *out = malloc(len + 1);
|
||||
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
memcpy(out, in, len);
|
||||
|
||||
*(out + len) = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool
|
||||
urldecode(char *buf)
|
||||
{
|
||||
char *c, *p;
|
||||
|
||||
if (!buf || !*buf)
|
||||
return true;
|
||||
|
||||
#define hex(x) \
|
||||
(((x) <= '9') ? ((x) - '0') : \
|
||||
(((x) <= 'F') ? ((x) - 'A' + 10) : \
|
||||
((x) - 'a' + 10)))
|
||||
|
||||
for (c = p = buf; *p; c++)
|
||||
{
|
||||
if (*p == '%')
|
||||
{
|
||||
if (!isxdigit(*(p + 1)) || !isxdigit(*(p + 2)))
|
||||
return false;
|
||||
|
||||
*c = (char)(16 * hex(*(p + 1)) + hex(*(p + 2)));
|
||||
|
||||
p += 3;
|
||||
}
|
||||
else if (*p == '+')
|
||||
{
|
||||
*c = ' ';
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*c = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
*c = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
postdecode(char **fields, int n_fields)
|
||||
{
|
||||
char *p;
|
||||
const char *var;
|
||||
static char buf[1024];
|
||||
int i, len, field, found = 0;
|
||||
|
||||
var = getenv("CONTENT_TYPE");
|
||||
|
||||
if (!var || strncmp(var, "application/x-www-form-urlencoded", 33))
|
||||
return false;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if ((len = read(0, buf, sizeof(buf) - 1)) > 0)
|
||||
{
|
||||
for (p = buf, i = 0; i <= len; i++)
|
||||
{
|
||||
if (buf[i] == '=')
|
||||
{
|
||||
buf[i] = 0;
|
||||
|
||||
for (field = 0; field < (n_fields * 2); field += 2)
|
||||
{
|
||||
if (!strcmp(p, fields[field]))
|
||||
{
|
||||
fields[field + 1] = buf + i + 1;
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (buf[i] == '&' || buf[i] == '\0')
|
||||
{
|
||||
buf[i] = 0;
|
||||
|
||||
if (found >= n_fields)
|
||||
break;
|
||||
|
||||
p = buf + i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (field = 0; field < (n_fields * 2); field += 2)
|
||||
if (!urldecode(fields[field + 1]))
|
||||
return false;
|
||||
|
||||
return (found >= n_fields);
|
||||
}
|
||||
|
||||
static int
|
||||
response(bool success, const char *message)
|
||||
{
|
||||
char *md5;
|
||||
struct stat s;
|
||||
|
||||
printf("Status: 200 OK\r\n");
|
||||
printf("Content-Type: text/plain\r\n\r\n{\n");
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (!stat(st.filename, &s) && (md5 = md5sum(st.filename)) != NULL)
|
||||
printf("\t\"size\": %u,\n\t\"checksum\": \"%s\"\n",
|
||||
(unsigned int)s.st_size, md5);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message)
|
||||
printf("\t\"message\": \"%s\",\n", message);
|
||||
|
||||
printf("\t\"failure\": [ %u, \"%s\" ]\n", errno, strerror(errno));
|
||||
|
||||
if (st.filefd > -1)
|
||||
unlink(st.filename);
|
||||
}
|
||||
|
||||
printf("}\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
failure(int e, const char *message)
|
||||
{
|
||||
printf("Status: 500 Internal Server failure\r\n");
|
||||
printf("Content-Type: text/plain\r\n\r\n");
|
||||
printf("%s", message);
|
||||
|
||||
if (e)
|
||||
printf(": %s", strerror(e));
|
||||
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
static int
|
||||
filecopy(void)
|
||||
{
|
||||
int len;
|
||||
char buf[4096];
|
||||
|
||||
if (!st.filedata)
|
||||
{
|
||||
close(st.tempfd);
|
||||
errno = EINVAL;
|
||||
return response(false, "No file data received");
|
||||
}
|
||||
|
||||
if (lseek(st.tempfd, 0, SEEK_SET) < 0)
|
||||
{
|
||||
close(st.tempfd);
|
||||
return response(false, "Failed to rewind temp file");
|
||||
}
|
||||
|
||||
st.filefd = open(st.filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
|
||||
if (st.filefd < 0)
|
||||
{
|
||||
close(st.tempfd);
|
||||
return response(false, "Failed to open target file");
|
||||
}
|
||||
|
||||
while ((len = read(st.tempfd, buf, sizeof(buf))) > 0)
|
||||
{
|
||||
if (write(st.filefd, buf, len) != len)
|
||||
{
|
||||
close(st.tempfd);
|
||||
close(st.filefd);
|
||||
return response(false, "I/O failure while writing target file");
|
||||
}
|
||||
}
|
||||
|
||||
close(st.tempfd);
|
||||
close(st.filefd);
|
||||
|
||||
if (chmod(st.filename, st.filemode))
|
||||
return response(false, "Failed to chmod target file");
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
static int
|
||||
header_field(multipart_parser *p, const char *data, size_t len)
|
||||
{
|
||||
st.is_content_disposition = !strncasecmp(data, "Content-Disposition", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
header_value(multipart_parser *p, const char *data, size_t len)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!st.is_content_disposition)
|
||||
return 0;
|
||||
|
||||
if (len < 10 || strncasecmp(data, "form-data", 9))
|
||||
return 0;
|
||||
|
||||
for (data += 9, len -= 9; *data == ' ' || *data == ';'; data++, len--);
|
||||
|
||||
if (len < 8 || strncasecmp(data, "name=\"", 6))
|
||||
return 0;
|
||||
|
||||
for (data += 6, len -= 6, i = 0; i <= len; i++)
|
||||
{
|
||||
if (*(data + i) != '"')
|
||||
continue;
|
||||
|
||||
for (j = 1; j < sizeof(parts) / sizeof(parts[0]); j++)
|
||||
if (!strncmp(data, parts[j], i))
|
||||
st.parttype = j;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
data_begin_cb(multipart_parser *p)
|
||||
{
|
||||
|
||||
if (st.parttype == PART_FILEDATA)
|
||||
{
|
||||
if (!st.sessionid)
|
||||
return response(false, "File data without session");
|
||||
|
||||
if (!st.filename)
|
||||
return response(false, "File data without name");
|
||||
|
||||
st.filefd = open(st.filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
|
||||
if (st.filefd < 0)
|
||||
return response(false, "Failed to create file");
|
||||
|
||||
//unlink(tmpname);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
data_cb(multipart_parser *p, const char *data, size_t len)
|
||||
{
|
||||
switch (st.parttype)
|
||||
{
|
||||
case PART_SESSIONID:
|
||||
st.sessionid = datadup(data, len);
|
||||
break;
|
||||
|
||||
case PART_FILENAME:
|
||||
st.filename = datadup(data, len);
|
||||
break;
|
||||
|
||||
case PART_FILEMODE:
|
||||
st.filemode = strtoul(data, NULL, 8);
|
||||
break;
|
||||
|
||||
case PART_FILEDATA:
|
||||
if (write(st.filefd, data, len) != len)
|
||||
{
|
||||
close(st.filefd);
|
||||
return response(false, "I/O failure while writing temporary file");
|
||||
}
|
||||
|
||||
if (!st.filedata)
|
||||
st.filedata = !!len;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
data_end_cb(multipart_parser *p)
|
||||
{
|
||||
if (st.parttype == PART_SESSIONID)
|
||||
{
|
||||
if (!session_access(st.sessionid, "upload", "write"))
|
||||
{
|
||||
errno = EPERM;
|
||||
return response(false, "Upload permission denied");
|
||||
}
|
||||
}
|
||||
else if (st.parttype == PART_FILEDATA)
|
||||
{
|
||||
if (st.filefd < 0)
|
||||
return response(false, "Internal program failure");
|
||||
|
||||
//if (filecopy())
|
||||
// return -1;
|
||||
|
||||
return response(true, NULL);
|
||||
}
|
||||
|
||||
st.parttype = PART_UNKNOWN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static multipart_parser *
|
||||
init_parser(void)
|
||||
{
|
||||
char *boundary;
|
||||
const char *var;
|
||||
|
||||
multipart_parser *p;
|
||||
static multipart_parser_settings s = {
|
||||
.on_part_data = data_cb,
|
||||
.on_headers_complete = data_begin_cb,
|
||||
.on_part_data_end = data_end_cb,
|
||||
.on_header_field = header_field,
|
||||
.on_header_value = header_value
|
||||
};
|
||||
|
||||
var = getenv("CONTENT_TYPE");
|
||||
|
||||
if (!var || strncmp(var, "multipart/form-data;", 20))
|
||||
return NULL;
|
||||
|
||||
for (var += 20; *var && *var != '='; var++);
|
||||
|
||||
if (*var++ != '=')
|
||||
return NULL;
|
||||
|
||||
boundary = malloc(strlen(var) + 3);
|
||||
|
||||
if (!boundary)
|
||||
return NULL;
|
||||
|
||||
strcpy(boundary, "--");
|
||||
strcpy(boundary + 2, var);
|
||||
|
||||
st.filefd = -1;
|
||||
st.filemode = 0600;
|
||||
|
||||
p = multipart_parser_init(boundary, &s);
|
||||
|
||||
free(boundary);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
main_upload(int argc, char *argv[])
|
||||
{
|
||||
int rem, len;
|
||||
char buf[4096];
|
||||
multipart_parser *p;
|
||||
|
||||
p = init_parser();
|
||||
|
||||
if (!p)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return response(false, "Invalid request");
|
||||
}
|
||||
|
||||
while ((len = read(0, buf, sizeof(buf))) > 0)
|
||||
{
|
||||
rem = multipart_parser_execute(p, buf, len);
|
||||
|
||||
if (rem < len)
|
||||
break;
|
||||
}
|
||||
|
||||
multipart_parser_free(p);
|
||||
|
||||
/* read remaining post data */
|
||||
while ((len = read(0, buf, sizeof(buf))) > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
static int exec_command(const char *cmd, char **out){
|
||||
FILE *fd;
|
||||
int buffer_size = 4096;
|
||||
char *data = malloc(buffer_size);
|
||||
char *pdata = data;
|
||||
int c;
|
||||
|
||||
if ((fd = popen(cmd, "r"))) {
|
||||
while((c = fgetc(fd)) != EOF){
|
||||
*pdata = c;
|
||||
pdata++;
|
||||
if(pdata == (data + buffer_size)){
|
||||
size_t size = buffer_size;
|
||||
buffer_size += 4096;
|
||||
data = realloc(data, buffer_size);
|
||||
pdata = data + size;
|
||||
}
|
||||
}
|
||||
pclose(fd);
|
||||
}
|
||||
*out = data;
|
||||
return (int)(pdata - data);
|
||||
}*/
|
||||
|
||||
static void run_child(const char *cmd){
|
||||
FILE *fd;
|
||||
int c;
|
||||
|
||||
if ((fd = popen(cmd, "r"))) {
|
||||
while((c = fgetc(fd)) != EOF){
|
||||
putc(c, stdout);
|
||||
}
|
||||
pclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
main_backup(int argc, char **argv)
|
||||
{
|
||||
//pid_t pid;
|
||||
time_t now;
|
||||
/*int len;
|
||||
int fds[2];
|
||||
char buf[4096];*/
|
||||
char datestr[16] = { 0 };
|
||||
char hostname[64] = { 0 };
|
||||
char *fields[] = { "sessionid", NULL, "password", NULL };
|
||||
|
||||
if (!postdecode(fields, 2) || !session_access(fields[1], "backup", "read"))
|
||||
return failure(0, "Backup permission denied");
|
||||
|
||||
now = time(NULL);
|
||||
strftime(datestr, sizeof(datestr) - 1, "%Y-%m-%d", localtime(&now));
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname) - 1))
|
||||
sprintf(hostname, "OpenWrt");
|
||||
|
||||
printf("Status: 200 OK\r\n");
|
||||
|
||||
char cmd[256];
|
||||
const char *enctype = "";
|
||||
if(fields[3] && strlen(fields[3]) > 0){
|
||||
snprintf(cmd, sizeof(cmd), "sysupgrade --create-backup - --password %s", fields[3]);
|
||||
enctype = "encrypted";
|
||||
} else {
|
||||
snprintf(cmd, sizeof(cmd), "sysupgrade --create-backup -");
|
||||
}
|
||||
|
||||
printf("Content-Type: application/x-targz\r\n");
|
||||
printf("Content-Disposition: attachment; "
|
||||
"filename=\"backup-%s-%s-%s.tar.gz\"\r\n\r\n", enctype, hostname, datestr);
|
||||
|
||||
run_child(cmd);
|
||||
|
||||
/*
|
||||
if (pipe(fds))
|
||||
return failure(errno, "Failed to spawn pipe");
|
||||
|
||||
switch ((pid = fork()))
|
||||
{
|
||||
case -1:
|
||||
return failure(errno, "Failed to fork process");
|
||||
|
||||
case 0:
|
||||
dup2(fds[1], 1);
|
||||
|
||||
close(0);
|
||||
close(2);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
chdir("/");
|
||||
|
||||
if(fields[3]){
|
||||
execl("/sbin/sysupgrade", "/sbin/sysupgrade",
|
||||
"--create-backup", "-", "--password", fields[3] , NULL);
|
||||
} else {
|
||||
execl("/sbin/sysupgrade", "/sbin/sysupgrade",
|
||||
"--create-backup", "-", NULL);
|
||||
}
|
||||
return -1;
|
||||
|
||||
default:
|
||||
now = time(NULL);
|
||||
strftime(datestr, sizeof(datestr) - 1, "%Y-%m-%d", localtime(&now));
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname) - 1))
|
||||
sprintf(hostname, "OpenWrt");
|
||||
|
||||
printf("Status: 200 OK\r\n");
|
||||
printf("Content-Type: application/x-targz\r\n");
|
||||
printf("Content-Disposition: attachment; "
|
||||
"filename=\"backup-%s-%s.tar.gz\"\r\n\r\n", hostname, datestr);
|
||||
|
||||
while ((len = read(fds[0], buf, sizeof(buf))) > 0)
|
||||
fwrite(buf, len, 1, stdout);
|
||||
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
return 0;
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (strstr(argv[0], "juci-upload"))
|
||||
return main_upload(argc, argv);
|
||||
else if (strstr(argv[0], "juci-backup"))
|
||||
return main_backup(argc, argv);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
/* Based on node-formidable by Felix Geisendörfer
|
||||
* Igor Afonov - afonov@gmail.com - 2012
|
||||
* MIT License - http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "multipart_parser.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static void multipart_log(const char * format, ...)
|
||||
{
|
||||
#ifdef DEBUG_MULTIPART
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
fprintf(stderr, "[HTTP_MULTIPART_PARSER] %s:%d: ", __FILE__, __LINE__);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#define NOTIFY_CB(FOR) \
|
||||
do { \
|
||||
if (p->settings->on_##FOR) { \
|
||||
if (p->settings->on_##FOR(p) != 0) { \
|
||||
return i; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EMIT_DATA_CB(FOR, ptr, len) \
|
||||
do { \
|
||||
if (p->settings->on_##FOR) { \
|
||||
if (p->settings->on_##FOR(p, ptr, len) != 0) { \
|
||||
return i; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define LF 10
|
||||
#define CR 13
|
||||
|
||||
struct multipart_parser {
|
||||
void * data;
|
||||
|
||||
size_t index;
|
||||
size_t boundary_length;
|
||||
|
||||
unsigned char state;
|
||||
|
||||
const multipart_parser_settings* settings;
|
||||
|
||||
char* lookbehind;
|
||||
char multipart_boundary[1];
|
||||
};
|
||||
|
||||
enum state {
|
||||
s_uninitialized = 1,
|
||||
s_start,
|
||||
s_start_boundary,
|
||||
s_header_field_start,
|
||||
s_header_field,
|
||||
s_headers_almost_done,
|
||||
s_header_value_start,
|
||||
s_header_value,
|
||||
s_header_value_almost_done,
|
||||
s_part_data_start,
|
||||
s_part_data,
|
||||
s_part_data_almost_boundary,
|
||||
s_part_data_boundary,
|
||||
s_part_data_almost_end,
|
||||
s_part_data_end,
|
||||
s_part_data_final_hyphen,
|
||||
s_end
|
||||
};
|
||||
|
||||
multipart_parser* multipart_parser_init
|
||||
(const char *boundary, const multipart_parser_settings* settings) {
|
||||
|
||||
multipart_parser* p = malloc(sizeof(multipart_parser) +
|
||||
strlen(boundary) +
|
||||
strlen(boundary) + 9);
|
||||
|
||||
strcpy(p->multipart_boundary, boundary);
|
||||
p->boundary_length = strlen(boundary);
|
||||
|
||||
p->lookbehind = (p->multipart_boundary + p->boundary_length + 1);
|
||||
|
||||
p->index = 0;
|
||||
p->state = s_start;
|
||||
p->settings = settings;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void multipart_parser_free(multipart_parser* p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
void multipart_parser_set_data(multipart_parser *p, void *data) {
|
||||
p->data = data;
|
||||
}
|
||||
|
||||
void *multipart_parser_get_data(multipart_parser *p) {
|
||||
return p->data;
|
||||
}
|
||||
|
||||
size_t multipart_parser_execute(multipart_parser* p, const char *buf, size_t len) {
|
||||
size_t i = 0;
|
||||
size_t mark = 0;
|
||||
char c, cl;
|
||||
int is_last = 0;
|
||||
|
||||
while(i < len) {
|
||||
c = buf[i];
|
||||
is_last = (i == (len - 1));
|
||||
switch (p->state) {
|
||||
case s_start:
|
||||
multipart_log("s_start");
|
||||
p->index = 0;
|
||||
p->state = s_start_boundary;
|
||||
|
||||
/* fallthrough */
|
||||
case s_start_boundary:
|
||||
multipart_log("s_start_boundary");
|
||||
if (p->index == p->boundary_length) {
|
||||
if (c != CR) {
|
||||
return i;
|
||||
}
|
||||
p->index++;
|
||||
break;
|
||||
} else if (p->index == (p->boundary_length + 1)) {
|
||||
if (c != LF) {
|
||||
return i;
|
||||
}
|
||||
p->index = 0;
|
||||
NOTIFY_CB(part_data_begin);
|
||||
p->state = s_header_field_start;
|
||||
break;
|
||||
}
|
||||
if (c != p->multipart_boundary[p->index]) {
|
||||
return i;
|
||||
}
|
||||
p->index++;
|
||||
break;
|
||||
|
||||
case s_header_field_start:
|
||||
multipart_log("s_header_field_start");
|
||||
mark = i;
|
||||
p->state = s_header_field;
|
||||
|
||||
/* fallthrough */
|
||||
case s_header_field:
|
||||
multipart_log("s_header_field");
|
||||
if (c == CR) {
|
||||
p->state = s_headers_almost_done;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '-') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == ':') {
|
||||
EMIT_DATA_CB(header_field, buf + mark, i - mark);
|
||||
p->state = s_header_value_start;
|
||||
break;
|
||||
}
|
||||
|
||||
cl = tolower(c);
|
||||
if (cl < 'a' || cl > 'z') {
|
||||
multipart_log("invalid character in header name");
|
||||
return i;
|
||||
}
|
||||
if (is_last)
|
||||
EMIT_DATA_CB(header_field, buf + mark, (i - mark) + 1);
|
||||
break;
|
||||
|
||||
case s_headers_almost_done:
|
||||
multipart_log("s_headers_almost_done");
|
||||
if (c != LF) {
|
||||
return i;
|
||||
}
|
||||
|
||||
p->state = s_part_data_start;
|
||||
break;
|
||||
|
||||
case s_header_value_start:
|
||||
multipart_log("s_header_value_start");
|
||||
if (c == ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
mark = i;
|
||||
p->state = s_header_value;
|
||||
|
||||
/* fallthrough */
|
||||
case s_header_value:
|
||||
multipart_log("s_header_value");
|
||||
if (c == CR) {
|
||||
EMIT_DATA_CB(header_value, buf + mark, i - mark);
|
||||
p->state = s_header_value_almost_done;
|
||||
}
|
||||
if (is_last)
|
||||
EMIT_DATA_CB(header_value, buf + mark, (i - mark) + 1);
|
||||
break;
|
||||
|
||||
case s_header_value_almost_done:
|
||||
multipart_log("s_header_value_almost_done");
|
||||
if (c != LF) {
|
||||
return i;
|
||||
}
|
||||
p->state = s_header_field_start;
|
||||
break;
|
||||
|
||||
case s_part_data_start:
|
||||
multipart_log("s_part_data_start");
|
||||
NOTIFY_CB(headers_complete);
|
||||
mark = i;
|
||||
p->state = s_part_data;
|
||||
|
||||
/* fallthrough */
|
||||
case s_part_data:
|
||||
multipart_log("s_part_data");
|
||||
if (c == CR) {
|
||||
EMIT_DATA_CB(part_data, buf + mark, i - mark);
|
||||
mark = i;
|
||||
p->state = s_part_data_almost_boundary;
|
||||
p->lookbehind[0] = CR;
|
||||
break;
|
||||
}
|
||||
if (is_last)
|
||||
EMIT_DATA_CB(part_data, buf + mark, (i - mark) + 1);
|
||||
break;
|
||||
|
||||
case s_part_data_almost_boundary:
|
||||
multipart_log("s_part_data_almost_boundary");
|
||||
if (c == LF) {
|
||||
p->state = s_part_data_boundary;
|
||||
p->lookbehind[1] = LF;
|
||||
p->index = 0;
|
||||
break;
|
||||
}
|
||||
EMIT_DATA_CB(part_data, p->lookbehind, 1);
|
||||
p->state = s_part_data;
|
||||
mark = i --;
|
||||
break;
|
||||
|
||||
case s_part_data_boundary:
|
||||
multipart_log("s_part_data_boundary");
|
||||
if (p->multipart_boundary[p->index] != c) {
|
||||
EMIT_DATA_CB(part_data, p->lookbehind, 2 + p->index);
|
||||
p->state = s_part_data;
|
||||
mark = i --;
|
||||
break;
|
||||
}
|
||||
p->lookbehind[2 + p->index] = c;
|
||||
if ((++ p->index) == p->boundary_length) {
|
||||
NOTIFY_CB(part_data_end);
|
||||
p->state = s_part_data_almost_end;
|
||||
}
|
||||
break;
|
||||
|
||||
case s_part_data_almost_end:
|
||||
multipart_log("s_part_data_almost_end");
|
||||
if (c == '-') {
|
||||
p->state = s_part_data_final_hyphen;
|
||||
break;
|
||||
}
|
||||
if (c == CR) {
|
||||
p->state = s_part_data_end;
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
|
||||
case s_part_data_final_hyphen:
|
||||
multipart_log("s_part_data_final_hyphen");
|
||||
if (c == '-') {
|
||||
NOTIFY_CB(body_end);
|
||||
p->state = s_end;
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
|
||||
case s_part_data_end:
|
||||
multipart_log("s_part_data_end");
|
||||
if (c == LF) {
|
||||
p->state = s_header_field_start;
|
||||
NOTIFY_CB(part_data_begin);
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
|
||||
case s_end:
|
||||
multipart_log("s_end: %02X", (int) c);
|
||||
break;
|
||||
|
||||
default:
|
||||
multipart_log("Multipart parser unrecoverable error");
|
||||
return 0;
|
||||
}
|
||||
++ i;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/* Based on node-formidable by Felix Geisendörfer
|
||||
* Igor Afonov - afonov@gmail.com - 2012
|
||||
* MIT License - http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
#ifndef _multipart_parser_h
|
||||
#define _multipart_parser_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct multipart_parser multipart_parser;
|
||||
typedef struct multipart_parser_settings multipart_parser_settings;
|
||||
typedef struct multipart_parser_state multipart_parser_state;
|
||||
|
||||
typedef int (*multipart_data_cb) (multipart_parser*, const char *at, size_t length);
|
||||
typedef int (*multipart_notify_cb) (multipart_parser*);
|
||||
|
||||
struct multipart_parser_settings {
|
||||
multipart_data_cb on_header_field;
|
||||
multipart_data_cb on_header_value;
|
||||
multipart_data_cb on_part_data;
|
||||
|
||||
multipart_notify_cb on_part_data_begin;
|
||||
multipart_notify_cb on_headers_complete;
|
||||
multipart_notify_cb on_part_data_end;
|
||||
multipart_notify_cb on_body_end;
|
||||
};
|
||||
|
||||
multipart_parser* multipart_parser_init
|
||||
(const char *boundary, const multipart_parser_settings* settings);
|
||||
|
||||
void multipart_parser_free(multipart_parser* p);
|
||||
|
||||
size_t multipart_parser_execute(multipart_parser* p, const char *buf, size_t len);
|
||||
|
||||
void multipart_parser_set_data(multipart_parser* p, void* data);
|
||||
void * multipart_parser_get_data(multipart_parser* p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue