From 52191dc080c8036e570615bb4a6d682a03a9a1ae Mon Sep 17 00:00:00 2001 From: bmatt Date: Tue, 25 Feb 2020 04:34:38 +0000 Subject: [PATCH] Added DataTables for table sorting, pagination, and searching of bill_table for dashboard. Issue #112 --- .uwsgi_plugins_builder/uwsgi.h | 4960 +++++++++++++++++ .uwsgi_plugins_builder/uwsgiconfig.py | 1665 ++++++ ihatemoney/static/css/datatables.min.css | 15 + ihatemoney/static/images/sort_asc.png | Bin 0 -> 160 bytes .../static/images/sort_asc_disabled.png | Bin 0 -> 148 bytes ihatemoney/static/images/sort_both.png | Bin 0 -> 201 bytes ihatemoney/static/images/sort_desc.png | Bin 0 -> 158 bytes .../static/images/sort_desc_disabled.png | Bin 0 -> 146 bytes ihatemoney/static/js/datatables.min.js | 194 + ihatemoney/templates/dashboard.html | 32 +- ihatemoney/templates/layout.html | 2 + 11 files changed, 6860 insertions(+), 8 deletions(-) create mode 100644 .uwsgi_plugins_builder/uwsgi.h create mode 100644 .uwsgi_plugins_builder/uwsgiconfig.py create mode 100644 ihatemoney/static/css/datatables.min.css create mode 100644 ihatemoney/static/images/sort_asc.png create mode 100644 ihatemoney/static/images/sort_asc_disabled.png create mode 100644 ihatemoney/static/images/sort_both.png create mode 100644 ihatemoney/static/images/sort_desc.png create mode 100644 ihatemoney/static/images/sort_desc_disabled.png create mode 100644 ihatemoney/static/js/datatables.min.js diff --git a/.uwsgi_plugins_builder/uwsgi.h b/.uwsgi_plugins_builder/uwsgi.h new file mode 100644 index 00000000..a5368795 --- /dev/null +++ b/.uwsgi_plugins_builder/uwsgi.h @@ -0,0 +1,4960 @@ +/* uWSGI */ + +/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 -il0 */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define UWSGI_PLUGIN_API 1 + +#define UWSGI_HAS_OFFLOAD_UBUFS 1 + +#define UMAX16 65536 +#define UMAX8 256 + +#define UMAX64_STR "18446744073709551615" +#define MAX64_STR "-9223372036854775808" + +#define UWSGI_END_OF_OPTIONS { NULL, 0, 0, NULL, NULL, NULL, 0}, + +#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__); +#define uwsgi_error_realpath(x) uwsgi_log("realpath() of %s failed: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__); +#define uwsgi_log_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log(x); +#define uwsgi_error_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__); +#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log +#define uwsgi_log_alarm(x, ...) uwsgi_log("[uwsgi-alarm" x, __VA_ARGS__) +#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1); +#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__); +#define uwsgi_req_error(x) if (wsgi_req->uri_len > 0 && wsgi_req->method_len > 0 && wsgi_req->remote_addr_len > 0) uwsgi_log_verbose("%s: %s [%s line %d] during %.*s %.*s (%.*s)\n", x, strerror(errno), __FILE__, __LINE__,\ + wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr); else uwsgi_log_verbose("%s %s [%s line %d] \n",x, strerror(errno), __FILE__, __LINE__); +#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__); +#define uwsgi_rawlog(x) if (write(2, x, strlen(x)) != strlen(x)) uwsgi_error("write()") +#define uwsgi_str(x) uwsgi_concat2(x, (char *)"") + +#define uwsgi_notify(x) if (uwsgi.notify) uwsgi.notify(x) +#define uwsgi_notify_ready() uwsgi.shared->ready = 1 ; if (uwsgi.notify_ready) uwsgi.notify_ready() + +#define uwsgi_apps uwsgi.workers[uwsgi.mywid].apps +#define uwsgi_apps_cnt uwsgi.workers[uwsgi.mywid].apps_cnt + +#define wsgi_req_time ((wsgi_req->end_of_request-wsgi_req->start_of_request)/1000) + +#define thunder_lock if (!uwsgi.is_et) {\ + if (uwsgi.use_thunder_lock) {\ + uwsgi_lock(uwsgi.the_thunder_lock);\ + }\ + else if (uwsgi.threads > 1) {\ + pthread_mutex_lock(&uwsgi.thunder_mutex);\ + }\ + } + +#define thunder_unlock if (!uwsgi.is_et) {\ + if (uwsgi.use_thunder_lock) {\ + uwsgi_unlock(uwsgi.the_thunder_lock);\ + }\ + else if (uwsgi.threads > 1) {\ + pthread_mutex_unlock(&uwsgi.thunder_mutex);\ + }\ + } + + +#define uwsgi_n64(x) strtoul(x, NULL, 10) + +#define ushared uwsgi.shared + +#define UWSGI_OPT_IMMEDIATE (1 << 0) +#define UWSGI_OPT_MASTER (1 << 1) +#define UWSGI_OPT_LOG_MASTER (1 << 2) +#define UWSGI_OPT_THREADS (1 << 3) +#define UWSGI_OPT_CHEAPER (1 << 4) +#define UWSGI_OPT_VHOST (1 << 5) +#define UWSGI_OPT_MEMORY (1 << 6) +#define UWSGI_OPT_PROCNAME (1 << 7) +#define UWSGI_OPT_LAZY (1 << 8) +#define UWSGI_OPT_NO_INITIAL (1 << 9) +#define UWSGI_OPT_NO_SERVER (1 << 10) +#define UWSGI_OPT_POST_BUFFERING (1 << 11) +#define UWSGI_OPT_CLUSTER (1 << 12) +#define UWSGI_OPT_MIME (1 << 13) +#define UWSGI_OPT_REQ_LOG_MASTER (1 << 14) +#define UWSGI_OPT_METRICS (1 << 15) + +#define MAX_GENERIC_PLUGINS 128 +#define MAX_GATEWAYS 64 +#define MAX_TIMERS 64 +#define MAX_CRONS 64 + +#define UWSGI_VIA_SENDFILE 1 +#define UWSGI_VIA_ROUTE 2 +#define UWSGI_VIA_OFFLOAD 3 + +#ifndef UWSGI_LOAD_EMBEDDED_PLUGINS +#define UWSGI_LOAD_EMBEDDED_PLUGINS +#endif + +#ifndef UWSGI_DECLARE_EMBEDDED_PLUGINS +#define UWSGI_DECLARE_EMBEDDED_PLUGINS +#endif + +#ifdef UWSGI_EMBED_CONFIG + extern char UWSGI_EMBED_CONFIG; + extern char UWSGI_EMBED_CONFIG_END; +#endif + +#define UDEP(pname) extern struct uwsgi_plugin pname##_plugin; + +#define ULEP(pname)\ + if (pname##_plugin.request) {\ + uwsgi.p[pname##_plugin.modifier1] = &pname##_plugin;\ + if (uwsgi.p[pname##_plugin.modifier1]->on_load)\ + uwsgi.p[pname##_plugin.modifier1]->on_load();\ + }\ + else {\ + if (uwsgi.gp_cnt >= MAX_GENERIC_PLUGINS) {\ + uwsgi_log("you have embedded too much generic plugins !!!\n");\ + exit(1);\ + }\ + uwsgi.gp[uwsgi.gp_cnt] = &pname##_plugin;\ + if (uwsgi.gp[uwsgi.gp_cnt]->on_load)\ + uwsgi.gp[uwsgi.gp_cnt]->on_load();\ + uwsgi.gp_cnt++;\ + }\ + + +#define fill_plugin_table(x, up)\ + if (up->request) {\ + uwsgi.p[x] = up;\ + }\ + else {\ + if (uwsgi.gp_cnt >= MAX_GENERIC_PLUGINS) {\ + uwsgi_log("you have embedded too much generic plugins !!!\n");\ + exit(1);\ + }\ + uwsgi.gp[uwsgi.gp_cnt] = up;\ + uwsgi.gp_cnt++;\ + }\ + +#define uwsgi_foreach(x, y) for(x=y;x;x = x->next) + +#define uwsgi_foreach_token(x, y, z, w) for(z=strtok_r(x, y, &w);z;z = strtok_r(NULL, y, &w)) + + +#ifndef __need_IOV_MAX +#define __need_IOV_MAX +#endif + +#ifdef __sun__ +#ifndef _XPG4_2 +#define _XPG4_2 +#endif +#ifndef __EXTENSIONS__ +#define __EXTENSIONS__ +#endif +#endif + +#if defined(__linux__) || defined(__GNUC__) +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#ifndef __USE_GNU +#define __USE_GNU +#endif +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef __linux__ +#ifndef MSG_FASTOPEN +#define MSG_FASTOPEN 0x20000000 +#endif +#endif +#include + +#include + +#ifdef UWSGI_UUID +#include +#endif + +#include +#include +#include +#ifdef __linux__ +#ifndef TCP_FASTOPEN +#define TCP_FASTOPEN 23 +#endif +#endif +#include + +#if defined(__GNU_kFreeBSD__) +#include +#endif + +#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__) +#include +#include +#include +#include +#ifdef UWSGI_HAS_FREEBSD_LIBJAIL +#include +#endif +#endif + +#include +#include + +#include +#include +#ifndef __USE_ISOC99 +#define __USE_ISOC99 +#endif +#include +#include +#include + +#ifdef UWSGI_HAS_IFADDRS +#include +#endif + + +#include +#include + + +#include + + +#ifdef __linux__ +#include +#include +#include +#endif + +#if defined(__linux) || defined(__FreeBSD__) || defined(__GNU_kFreeBSD__) +#include +#endif + +#ifdef __linux__ +extern int pivot_root(const char *new_root, const char *put_old); +#endif + +#include + +#include + +#ifndef UWSGI_PLUGIN_BASE +#define UWSGI_PLUGIN_BASE "" +#endif + +#include +#include +#include + +#include + +#include +#ifndef WAIT_ANY +#define WAIT_ANY (-1) +#endif + +#ifdef __APPLE__ +#ifndef MAC_OS_X_VERSION_MIN_REQUIRED +#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4 +#endif +#include +#endif + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#ifdef __APPLE__ +#include +#include +#include +#endif + +#ifdef _POSIX_C_SOURCE +#undef _POSIX_C_SOURCE +#endif +#if defined(__sun__) +#define WAIT_ANY (-1) +#include +#define PRIO_MAX 20 +#endif + +#if defined(__HAIKU__) || defined(__CYGWIN__) +#ifndef WAIT_ANY +#define WAIT_ANY (-1) +#endif +#define PRIO_MAX 20 +#endif + +#include + +#ifdef __linux__ +#include +#include +#elif defined(__GNU_kFreeBSD__) +#include +#include +#elif defined(__sun__) +#include +#include +#elif defined(__HAIKU__) +#elif defined(__CYGWIN__) +#elif defined(__HURD__) +#else +#include +#endif + +#ifdef UWSGI_CAP +#include +#endif + +#ifdef __HAIKU__ +#include +#endif + +#undef _XOPEN_SOURCE +#ifdef __sun__ +#undef __EXTENSIONS__ +#endif +#ifdef _GNU_SOURCE +#undef _GNU_SOURCE +#endif + +#define UWSGI_CACHE_FLAG_UNGETTABLE 0x01 +#define UWSGI_CACHE_FLAG_UPDATE 1 << 1 +#define UWSGI_CACHE_FLAG_LOCAL 1 << 2 +#define UWSGI_CACHE_FLAG_ABSEXPIRE 1 << 3 +#define UWSGI_CACHE_FLAG_MATH 1 << 4 +#define UWSGI_CACHE_FLAG_INC 1 << 5 +#define UWSGI_CACHE_FLAG_DEC 1 << 6 +#define UWSGI_CACHE_FLAG_MUL 1 << 7 +#define UWSGI_CACHE_FLAG_DIV 1 << 8 +#define UWSGI_CACHE_FLAG_FIXEXPIRE 1 << 9 + +#ifdef UWSGI_SSL +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define UWSGI_SSL_SESSION_CACHE +#endif +#endif + +#include + +#ifdef __CYGWIN__ +#define __WINCRYPT_H__ +#include +#ifdef UWSGI_UUID +#undef uuid_t +#endif +#undef CMSG_DATA +#define CMSG_DATA(cmsg) \ + ((unsigned char *) ((struct cmsghdr *)(cmsg) + 1)) +#endif + +struct uwsgi_buffer { + char *buf; + size_t pos; + size_t len; + size_t limit; +#ifdef UWSGI_DEBUG_BUFFER + int freed; +#endif +}; + +struct uwsgi_string_list { + char *value; + size_t len; + uint64_t custom; + uint64_t custom2; + void *custom_ptr; + struct uwsgi_string_list *next; +}; + +struct uwsgi_custom_option { + char *name; + char *value; + int has_args; + struct uwsgi_custom_option *next; +}; + +struct uwsgi_lock_item { + char *id; + void *lock_ptr; + int rw; + pid_t pid; + int can_deadlock; + struct uwsgi_lock_item *next; +}; + + +struct uwsgi_lock_ops { + struct uwsgi_lock_item *(*lock_init) (char *); + pid_t(*lock_check) (struct uwsgi_lock_item *); + void (*lock) (struct uwsgi_lock_item *); + void (*unlock) (struct uwsgi_lock_item *); + + struct uwsgi_lock_item *(*rwlock_init) (char *); + pid_t(*rwlock_check) (struct uwsgi_lock_item *); + void (*rlock) (struct uwsgi_lock_item *); + void (*wlock) (struct uwsgi_lock_item *); + void (*rwunlock) (struct uwsgi_lock_item *); +}; + +#define uwsgi_lock_init(x) uwsgi.lock_ops.lock_init(x) +#define uwsgi_lock_check(x) uwsgi.lock_ops.lock_check(x) +#define uwsgi_lock(x) uwsgi.lock_ops.lock(x) +#define uwsgi_unlock(x) uwsgi.lock_ops.unlock(x) + +#define uwsgi_rwlock_init(x) uwsgi.lock_ops.rwlock_init(x) +#define uwsgi_rwlock_check(x) uwsgi.lock_ops.rwlock_check(x) +#define uwsgi_rlock(x) uwsgi.lock_ops.rlock(x) +#define uwsgi_wlock(x) uwsgi.lock_ops.wlock(x) +#define uwsgi_rwunlock(x) uwsgi.lock_ops.rwunlock(x) + +#define uwsgi_wait_read_req(x) uwsgi.wait_read_hook(x->fd, uwsgi.socket_timeout) ; x->switches++ +#define uwsgi_wait_write_req(x) uwsgi.wait_write_hook(x->fd, uwsgi.socket_timeout) ; x->switches++ + +#ifdef UWSGI_PCRE +#include +#endif + +struct uwsgi_dyn_dict { + + char *key; + int keylen; + char *value; + int vallen; + + uint64_t hits; + int status; + + struct uwsgi_dyn_dict *prev; + struct uwsgi_dyn_dict *next; + +#ifdef UWSGI_PCRE + pcre *pattern; + pcre_extra *pattern_extra; +#endif + +}; + +struct uwsgi_hook { + char *name; + int (*func)(char *); + struct uwsgi_hook *next; +}; + +#ifdef UWSGI_PCRE +struct uwsgi_regexp_list { + + pcre *pattern; + pcre_extra *pattern_extra; + + uint64_t custom; + char *custom_str; + void *custom_ptr; + struct uwsgi_regexp_list *next; +}; +#endif + +struct uwsgi_rbtree { + struct uwsgi_rb_timer *root; + struct uwsgi_rb_timer *sentinel; +}; + +struct uwsgi_rb_timer { + uint8_t color; + struct uwsgi_rb_timer *parent; + struct uwsgi_rb_timer *left; + struct uwsgi_rb_timer *right; + uint64_t value; + void *data; +}; + +struct uwsgi_rbtree *uwsgi_init_rb_timer(void); +struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *, struct uwsgi_rb_timer *); +struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *, uint64_t, void *); +void uwsgi_del_rb_timer(struct uwsgi_rbtree *, struct uwsgi_rb_timer *); + + +union uwsgi_sockaddr { + struct sockaddr sa; + struct sockaddr_in sa_in; + struct sockaddr_un sa_un; +#ifdef AF_INET6 + struct sockaddr_in6 sa_in6; +#endif +}; + +union uwsgi_sockaddr_ptr { + struct sockaddr *sa; + struct sockaddr_in *sa_in; + struct sockaddr_un *sa_un; +#ifdef AF_INET6 + struct sockaddr_in6 *sa_in6; +#endif +}; + +// Gateways are processes (managed by the master) that extends the +// server core features +// -- Gateways can prefork or spawn threads -- + +struct uwsgi_gateway { + + char *name; + char *fullname; + void (*loop) (int, void *); + pid_t pid; + int num; + int use_signals; + + int internal_subscription_pipe[2]; + uint64_t respawns; + + uid_t uid; + gid_t gid; + + void *data; +}; + +struct uwsgi_gateway_socket { + + char *name; + size_t name_len; + int fd; + char *zerg; + + char *port; + int port_len; + + int no_defer; + + void *data; + int subscription; + int shared; + + char *owner; + struct uwsgi_gateway *gateway; + + struct uwsgi_gateway_socket *next; + + // could be useful for ssl + void *ctx; + // could be useful for plugins + int mode; + +}; + + +// Daemons are external processes maintained by the master + +struct uwsgi_daemon { + char *command; + pid_t pid; + uint64_t respawns; + time_t born; + time_t last_spawn; + int status; + int registered; + + int has_daemonized; + + char *pidfile; + int daemonize; + + // this is incremented every time a pidfile is not found + uint64_t pidfile_checks; + // frequency of pidfile checks (default 10 secs) + int freq; + + int control; + struct uwsgi_daemon *next; + + int stop_signal; + int reload_signal; + + uid_t uid; + uid_t gid; + + int honour_stdin; + + struct uwsgi_string_list *touch; + +#ifdef UWSGI_SSL + char *legion; +#endif + + int ns_pid; + int throttle; + + char *chdir; + + int max_throttle; +}; + +struct uwsgi_logger { + char *name; + char *id; + ssize_t(*func) (struct uwsgi_logger *, char *, size_t); + int configured; + int fd; + void *data; + union uwsgi_sockaddr addr; + socklen_t addr_len; + int count; + struct msghdr msg; + char *buf; + // used by choosen logger + char *arg; + struct uwsgi_logger *next; +}; + +#ifdef UWSGI_SSL +struct uwsgi_legion_node { + char *name; + uint16_t name_len; + uint64_t valor; + char uuid[37]; + char *scroll; + uint16_t scroll_len; + uint64_t checksum; + uint64_t lord_valor; + char lord_uuid[36]; + time_t last_seen; + struct uwsgi_legion_node *prev; + struct uwsgi_legion_node *next; +}; + +struct uwsgi_legion { + char *legion; + uint16_t legion_len; + uint64_t valor; + char *addr; + char *name; + uint16_t name_len; + pid_t pid; + char uuid[37]; + int socket; + + int quorum; + int changed; + // if set the next packet will be a death-announce + int dead; + + // set to 1 first time when quorum is reached + int joined; + + uint64_t checksum; + + char *scroll; + uint16_t scroll_len; + + char *lord_scroll; + uint16_t lord_scroll_len; + uint16_t lord_scroll_size; + + char lord_uuid[36]; + uint64_t lord_valor; + + time_t i_am_the_lord; + + time_t unix_check; + + time_t last_warning; + + struct uwsgi_lock_item *lock; + + EVP_CIPHER_CTX *encrypt_ctx; + EVP_CIPHER_CTX *decrypt_ctx; + + char *scrolls; + uint64_t scrolls_len; + uint64_t scrolls_max_size; + + // found nodes dynamic lists + struct uwsgi_legion_node *nodes_head; + struct uwsgi_legion_node *nodes_tail; + + // static list of nodes to send announces to + struct uwsgi_string_list *nodes; + struct uwsgi_string_list *lord_hooks; + struct uwsgi_string_list *unlord_hooks; + struct uwsgi_string_list *setup_hooks; + struct uwsgi_string_list *death_hooks; + struct uwsgi_string_list *join_hooks; + struct uwsgi_string_list *node_joined_hooks; + struct uwsgi_string_list *node_left_hooks; + + time_t suspended_til; + struct uwsgi_legion *next; +}; + +struct uwsgi_legion_action { + char *name; + int (*func) (struct uwsgi_legion *, char *); + char *log_msg; + struct uwsgi_legion_action *next; +}; +#endif + +struct uwsgi_queue_header { + uint64_t pos; + uint64_t pull_pos; +}; + +struct uwsgi_queue_item { + uint64_t size; + time_t ts; +}; + +struct uwsgi_hash_algo { + char *name; + uint32_t(*func) (char *, uint64_t); + struct uwsgi_hash_algo *next; +}; + +struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *); +void uwsgi_hash_algo_register(char *, uint32_t(*)(char *, uint64_t)); +void uwsgi_hash_algo_register_all(void); + +struct uwsgi_sharedarea { + int id; + int pages; + int fd; + struct uwsgi_lock_item *lock; + char *area; + uint64_t max_pos; + uint64_t updates; + uint64_t hits; + uint8_t honour_used; + uint64_t used; + void *obj; +}; + +// maintain alignment here !!! +struct uwsgi_cache_item { + // item specific flags + uint64_t flags; + // size of the key + uint64_t keysize; + // hash of the key + uint64_t hash; + // size of the value (64bit) + uint64_t valsize; + // block position (in non-bitmap mode maps to the key index) + uint64_t first_block; + // 64bit expiration (0 for immortal) + uint64_t expires; + // 64bit hits + uint64_t hits; + // previous same-hash item + uint64_t prev; + // next same-hash item + uint64_t next; + // previous lru item + uint64_t lru_prev; + // next lru item + uint64_t lru_next; + // key characters follows... + char key[]; +} __attribute__ ((__packed__)); + +struct uwsgi_cache { + char *name; + uint16_t name_len; + + uint64_t keysize; + uint64_t blocks; + uint64_t blocksize; + + struct uwsgi_hash_algo *hash; + uint64_t *hashtable; + uint32_t hashsize; + + uint64_t first_available_block; + uint64_t *unused_blocks_stack; + uint64_t unused_blocks_stack_ptr; + + uint8_t use_blocks_bitmap; + uint8_t *blocks_bitmap; + uint64_t blocks_bitmap_pos; + uint64_t blocks_bitmap_size; + + uint64_t max_items; + uint64_t max_item_size; + uint64_t n_items; + struct uwsgi_cache_item *items; + + uint8_t use_last_modified; + time_t last_modified_at; + + void *data; + + uint8_t no_expire; + uint64_t full; + uint64_t hits; + uint64_t miss; + + char *store; + uint64_t filesize; + uint64_t store_sync; + + int64_t math_initial; + + struct uwsgi_string_list *nodes; + int udp_node_socket; + struct uwsgi_string_list *sync_nodes; + struct uwsgi_string_list *udp_servers; + + struct uwsgi_lock_item *lock; + + struct uwsgi_cache *next; + + int ignore_full; + + uint64_t next_scan; + int purge_lru; + uint64_t lru_head; + uint64_t lru_tail; + + int store_delete; + int lazy_expire; + uint64_t sweep_on_full; + int clear_on_full; +}; + +struct uwsgi_option { + char *name; + int type; + int shortcut; + char *help; + void (*func) (char *, char *, void *); + void *data; + uint64_t flags; +}; + +struct uwsgi_opt { + char *key; + char *value; + int configured; +}; + +#define UWSGI_OK 0 +#define UWSGI_AGAIN 1 +#define UWSGI_ACCEPTING 2 +#define UWSGI_PAUSED 3 + +#ifdef __linux__ +#include +#if defined(__BYTE_ORDER__) +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define __BIG_ENDIAN__ 1 +#endif +#endif +#elif defined(__sun__) +#include +#ifdef _BIG_ENDIAN +#define __BIG_ENDIAN__ 1 +#endif +#elif defined(__APPLE__) +#include +#elif defined(__HAIKU__) +#elif defined(__HURD__) +#define PATH_MAX 8192 +#define RTLD_DEFAULT ((void *) 0) +#else +#include +#endif + +#define UWSGI_SPOOLER_EXTERNAL 1 + +#define UWSGI_MODIFIER_ADMIN_REQUEST 10 +#define UWSGI_MODIFIER_SPOOL_REQUEST 17 +#define UWSGI_MODIFIER_EVAL 22 +#define UWSGI_MODIFIER_FASTFUNC 26 +#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30 +#define UWSGI_MODIFIER_MESSAGE 31 +#define UWSGI_MODIFIER_MESSAGE_ARRAY 32 +#define UWSGI_MODIFIER_MESSAGE_MARSHAL 33 +#define UWSGI_MODIFIER_MULTICAST_ANNOUNCE 73 +#define UWSGI_MODIFIER_MULTICAST 74 +#define UWSGI_MODIFIER_PING 100 + +#define UWSGI_MODIFIER_RESPONSE 255 + +#define NL_SIZE 2 +#define H_SEP_SIZE 2 + +#define UWSGI_RELOAD_CODE 17 +#define UWSGI_END_CODE 30 +#define UWSGI_EXILE_CODE 26 +#define UWSGI_FAILED_APP_CODE 22 +#define UWSGI_DE_HIJACKED_CODE 173 +#define UWSGI_EXCEPTION_CODE 5 +#define UWSGI_QUIET_CODE 29 +#define UWSGI_BRUTAL_RELOAD_CODE 31 +#define UWSGI_GO_CHEAP_CODE 15 + +#define MAX_VARS 64 + +struct uwsgi_loop { + char *name; + void (*loop) (void); + struct uwsgi_loop *next; +}; + +struct wsgi_request; + +struct uwsgi_socket { + int fd; + char *name; + int name_len; + int family; + int bound; + int arg; + void *ctx; + + uint64_t queue; + uint64_t max_queue; + int no_defer; + + int auto_port; + // true if connection must be initialized for each core + int per_core; + + // this is the protocol internal name + char *proto_name; + + // call that when a request is accepted + int (*proto_accept) (struct wsgi_request *, int); + // call that to parse the request (without the body) + int (*proto) (struct wsgi_request *); + // call that to write reponse + int (*proto_write) (struct wsgi_request *, char *, size_t); + // call that to write headers (if a special case is needed for them) + int (*proto_write_headers) (struct wsgi_request *, char *, size_t); + // call that when sendfile() is invoked + int (*proto_sendfile) (struct wsgi_request *, int, size_t, size_t); + // call that to read the body of a request (could map to a simple read()) + ssize_t(*proto_read_body) (struct wsgi_request *, char *, size_t); + // hook to call when a new series of response headers is created + struct uwsgi_buffer *(*proto_prepare_headers) (struct wsgi_request *, char *, uint16_t); + // hook to call when a header must be added + struct uwsgi_buffer *(*proto_add_header) (struct wsgi_request *, char *, uint16_t, char *, uint16_t); + // last function to call before sending headers to the client + int (*proto_fix_headers) (struct wsgi_request *); + // hook to call when a request is closed + void (*proto_close) (struct wsgi_request *); + // special hook to call (if needed) in multithread mode + void (*proto_thread_fixup) (struct uwsgi_socket *, int); + // optimization for vectors + int (*proto_writev) (struct wsgi_request *, struct iovec *, size_t *); + + int edge_trigger; + int *retry; + + int can_offload; + + // this is a special map for having socket->thread mapping + int *fd_threads; + + // generally used by zeromq handlers + char uuid[37]; + void *pub; + void *pull; + pthread_key_t key; + + pthread_mutex_t lock; + + char *receiver; + + int disabled; + int recv_flag; + + struct uwsgi_socket *next; + int lazy; + int shared; + int from_shared; + + // used for avoiding vacuum mess + ino_t inode; + +#ifdef UWSGI_SSL + SSL_CTX *ssl_ctx; +#endif + +}; + +struct uwsgi_protocol { + char *name; + void (*func)(struct uwsgi_socket *); + struct uwsgi_protocol *next; +}; + +struct uwsgi_server; +struct uwsgi_instance; + +struct uwsgi_plugin { + + const char *name; + const char *alias; + uint8_t modifier1; + void *data; + void (*on_load) (void); + int (*init) (void); + void (*post_init) (void); + void (*post_fork) (void); + struct uwsgi_option *options; + void (*enable_threads) (void); + void (*init_thread) (int); + int (*request) (struct wsgi_request *); + void (*after_request) (struct wsgi_request *); + void (*preinit_apps) (void); + void (*init_apps) (void); + void (*postinit_apps) (void); + void (*fixup) (void); + void (*master_fixup) (int); + void (*master_cycle) (void); + int (*mount_app) (char *, char *); + int (*manage_udp) (char *, int, char *, int); + void (*suspend) (struct wsgi_request *); + void (*resume) (struct wsgi_request *); + + void (*harakiri) (int); + + void (*hijack_worker) (void); + void (*spooler_init) (void); + void (*atexit) (void); + + int (*magic) (char *, char *); + + void *(*encode_string) (char *); + char *(*decode_string) (void *); + int (*signal_handler) (uint8_t, void *); + char *(*code_string) (char *, char *, char *, char *, uint16_t); + + int (*spooler) (char *, char *, uint16_t, char *, size_t); + + uint64_t(*rpc) (void *, uint8_t, char **, uint16_t *, char **); + + void (*jail) (int (*)(void *), char **); + void (*post_jail) (void); + void (*before_privileges_drop) (void); + + int (*mule) (char *); + int (*mule_msg) (char *, size_t); + + void (*master_cleanup) (void); + + struct uwsgi_buffer* (*backtrace)(struct wsgi_request *); + struct uwsgi_buffer* (*exception_class)(struct wsgi_request *); + struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *); + struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *); + void (*exception_log)(struct wsgi_request *); + + void (*vassal)(struct uwsgi_instance *); + void (*vassal_before_exec)(struct uwsgi_instance *); + + int (*worker)(void); + + void (*early_post_jail) (void); +}; + +#ifdef UWSGI_PCRE +int uwsgi_regexp_build(char *, pcre **, pcre_extra **); +int uwsgi_regexp_match(pcre *, pcre_extra *, char *, int); +int uwsgi_regexp_match_ovec(pcre *, pcre_extra *, char *, int, int *, int); +int uwsgi_regexp_ovector(pcre *, pcre_extra *); +char *uwsgi_regexp_apply_ovec(char *, int, char *, int, int *, int); + +int uwsgi_regexp_match_pattern(char *pattern, char *str); +#endif + + + +struct uwsgi_app { + + uint8_t modifier1; + + char mountpoint[0xff]; + uint8_t mountpoint_len; + + void *interpreter; + void *callable; + + void **args; + void **environ; + + void *sendfile; + void *input; + void *error; + void *stream; + + // custom values you can use for internal purpose + void *responder0; + void *responder1; + void *responder2; + + void *eventfd_read; + void *eventfd_write; + + void *(*request_subhandler) (struct wsgi_request *, struct uwsgi_app *); + int (*response_subhandler) (struct wsgi_request *); + + int argc; + uint64_t requests; + uint64_t exceptions; + + char chdir[0xff]; + char touch_reload[0xff]; + + time_t touch_reload_mtime; + + void *gateway_version; + void *uwsgi_version; + void *uwsgi_node; + + time_t started_at; + time_t startup_time; + + uint64_t avg_response_time; +}; + +struct uwsgi_spooler { + + char dir[PATH_MAX]; + pid_t pid; + uint64_t respawned; + uint64_t tasks; + struct uwsgi_lock_item *lock; + time_t harakiri; + time_t user_harakiri; + + int mode; + + int running; + + int signal_pipe[2]; + + struct uwsgi_spooler *next; + + time_t cursed_at; + time_t no_mercy_at; +}; + +#ifdef UWSGI_ROUTING + +// go to the next route +#define UWSGI_ROUTE_NEXT 0 +// continue to the request handler +#define UWSGI_ROUTE_CONTINUE 1 +// close the request +#define UWSGI_ROUTE_BREAK 2 + +struct uwsgi_route { + + pcre *pattern; + pcre_extra *pattern_extra; + + char *orig_route; + + // one for each core + int *ovn; + int **ovector; + struct uwsgi_buffer **condition_ub; + + char *subject_str; + size_t subject_str_len; + size_t subject; + size_t subject_len; + + int (*if_func)(struct wsgi_request *, struct uwsgi_route *); + int if_negate; + int if_status; + + int (*func) (struct wsgi_request *, struct uwsgi_route *); + + void *data; + size_t data_len; + + void *data2; + size_t data2_len; + + void *data3; + size_t data3_len; + + void *data4; + size_t data4_len; + + // 64bit value for custom usage + uint64_t custom; + + uint64_t pos; + char *label; + size_t label_len; + + char *regexp; + char *action; + + // this is used by virtual route to free resources + void (*free)(struct uwsgi_route *); + + struct uwsgi_route *next; + +}; + +struct uwsgi_route_condition { + char *name; + int (*func)(struct wsgi_request *, struct uwsgi_route *); + struct uwsgi_route_condition *next; +}; + +struct uwsgi_route_var { + char *name; + uint16_t name_len; + char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *); + int need_free; + struct uwsgi_route_var *next; +}; + +struct uwsgi_router { + char *name; + int (*func) (struct uwsgi_route *, char *); + struct uwsgi_router *next; +}; + +#endif + +struct uwsgi_alarm; +struct uwsgi_alarm_instance { + char *name; + char *arg; + void *data_ptr; + uint8_t data8; + uint16_t data16; + uint32_t data32; + uint64_t data64; + + time_t last_run; + + char *last_msg; + size_t last_msg_size; + + struct uwsgi_alarm *alarm; + struct uwsgi_alarm_instance *next; +}; + +struct uwsgi_alarm { + char *name; + void (*init) (struct uwsgi_alarm_instance *); + void (*func) (struct uwsgi_alarm_instance *, char *, size_t); + struct uwsgi_alarm *next; +}; + +struct uwsgi_alarm_fd { + int fd; + size_t buf_len; + void *buf; + char *msg; + size_t msg_len; + struct uwsgi_alarm_instance *alarm; + struct uwsgi_alarm_fd *next; +}; + +struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int, char *, size_t, char *, size_t); + +#ifdef UWSGI_PCRE +struct uwsgi_alarm_ll { + struct uwsgi_alarm_instance *alarm; + struct uwsgi_alarm_ll *next; +}; + +struct uwsgi_alarm_log { + pcre *pattern; + pcre_extra *pattern_extra; + int negate; + struct uwsgi_alarm_ll *alarms; + struct uwsgi_alarm_log *next; +}; +#endif + +struct __attribute__ ((packed)) uwsgi_header { + uint8_t modifier1; + uint16_t pktsize; + uint8_t modifier2; +}; + +struct uwsgi_async_fd { + int fd; + int event; + struct uwsgi_async_fd *prev; + struct uwsgi_async_fd *next; +}; + +struct uwsgi_logvar { + char key[256]; + uint8_t keylen; + char val[256]; + uint8_t vallen; + struct uwsgi_logvar *next; +}; + +struct uwsgi_log_encoder { + char *name; + char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *); + int configured; + char *use_for; + char *args; + void *data; + struct uwsgi_log_encoder *next; +}; + +struct uwsgi_transformation { + int (*func)(struct wsgi_request *, struct uwsgi_transformation *); + struct uwsgi_buffer *chunk; + uint8_t can_stream; + uint8_t is_final; + uint8_t flushed; + void *data; + uint64_t round; + int fd; + struct uwsgi_buffer *ub; + uint64_t len; + uint64_t custom64; + struct uwsgi_transformation *next; +}; + +enum uwsgi_range { + UWSGI_RANGE_NOT_PARSED, + UWSGI_RANGE_PARSED, + UWSGI_RANGE_VALID, + UWSGI_RANGE_INVALID, +}; + +struct wsgi_request { + int fd; + struct uwsgi_header *uh; + + int app_id; + int dynamic; + int parsed; + + char *appid; + uint16_t appid_len; + + // This structure should not be used any more + // in favor of the union client_addr at the end + struct sockaddr_un c_addr; + int c_len; + + //iovec + struct iovec *hvec; + + uint64_t start_of_request; + uint64_t start_of_request_in_sec; + uint64_t end_of_request; + + char *uri; + uint16_t uri_len; + char *remote_addr; + uint16_t remote_addr_len; + char *remote_user; + uint16_t remote_user_len; + char *query_string; + uint16_t query_string_len; + char *protocol; + uint16_t protocol_len; + char *method; + uint16_t method_len; + char *scheme; + uint16_t scheme_len; + char *https; + uint16_t https_len; + char *script_name; + uint16_t script_name_len; + int script_name_pos; + + char *host; + uint16_t host_len; + + char *content_type; + uint16_t content_type_len; + + char *document_root; + uint16_t document_root_len; + + char *user_agent; + uint16_t user_agent_len; + + char *encoding; + uint16_t encoding_len; + + char *referer; + uint16_t referer_len; + + char *cookie; + uint16_t cookie_len; + + char *path_info; + uint16_t path_info_len; + int path_info_pos; + + char *authorization; + uint16_t authorization_len; + + uint16_t via; + + char *script; + uint16_t script_len; + char *module; + uint16_t module_len; + char *callable; + uint16_t callable_len; + char *home; + uint16_t home_len; + + char *file; + uint16_t file_len; + + char *paste; + uint16_t paste_len; + + char *chdir; + uint16_t chdir_len; + + char *touch_reload; + uint16_t touch_reload_len; + + char *cache_get; + uint16_t cache_get_len; + + char *if_modified_since; + uint16_t if_modified_since_len; + + int fd_closed; + + int sendfile_fd; + size_t sendfile_fd_chunk; + size_t sendfile_fd_size; + off_t sendfile_fd_pos; + void *sendfile_obj; + + uint16_t var_cnt; + uint16_t header_cnt; + + int do_not_log; + + int do_not_add_to_async_queue; + + int do_not_account; + + int status; + struct uwsgi_buffer *headers; + + size_t response_size; + size_t headers_size; + + int async_id; + int async_status; + + int switches; + size_t write_pos; + + int async_timed_out; + int async_ready_fd; + int async_last_ready_fd; + struct uwsgi_rb_timer *async_timeout; + struct uwsgi_async_fd *waiting_fds; + + void *async_app; + void *async_result; + void *async_placeholder; + void *async_args; + void *async_environ; + void *async_input; + void *async_sendfile; + + int async_force_again; + + int async_plagued; + + int suspended; + uint64_t write_errors; + uint64_t read_errors; + + int *ovector; + size_t post_cl; + size_t post_pos; + size_t post_readline_size; + size_t post_readline_pos; + size_t post_readline_watermark; + FILE *post_file; + char *post_readline_buf; + // this is used when no post buffering is in place + char *post_read_buf; + size_t post_read_buf_size; + char *post_buffering_buf; + // when set, do not send warnings about bad behaviours + int post_warning; + + // deprecated fields: size_t is 32bit on 32bit platform + size_t __range_from; + size_t __range_to; + + // current socket mapped to request + struct uwsgi_socket *socket; + + // check if headers are already sent + int headers_sent; + int headers_hvec; + + uint64_t proto_parser_pos; + uint64_t proto_parser_move; + int64_t proto_parser_status; + void *proto_parser_buf; + uint64_t proto_parser_buf_size; + void *proto_parser_remains_buf; + size_t proto_parser_remains; + + char *buffer; + + int log_this; + + int sigwait; + int signal_received; + + struct uwsgi_logvar *logvars; + struct uwsgi_string_list *additional_headers; + struct uwsgi_string_list *remove_headers; + + struct uwsgi_buffer *websocket_buf; + struct uwsgi_buffer *websocket_send_buf; + size_t websocket_need; + int websocket_phase; + uint8_t websocket_opcode; + size_t websocket_has_mask; + size_t websocket_size; + size_t websocket_pktsize; + time_t websocket_last_ping; + time_t websocket_last_pong; + int websocket_closed; + // websocket specific headers + char *http_sec_websocket_key; + uint16_t http_sec_websocket_key_len; + char *http_origin; + uint16_t http_origin_len; + char *http_sec_websocket_protocol; + uint16_t http_sec_websocket_protocol_len; + + + struct uwsgi_buffer *chunked_input_buf; + uint8_t chunked_input_parser_status; + ssize_t chunked_input_chunk_len; + size_t chunked_input_need; + uint8_t chunked_input_complete; + size_t chunked_input_decapitate; + + uint64_t stream_id; + + // avoid routing loops + int is_routing; + int is_final_routing; + int is_error_routing; + int is_response_routing; + int routes_applied; + int response_routes_applied; + // internal routing vm program counter + uint32_t route_pc; + uint32_t error_route_pc; + uint32_t response_route_pc; + uint32_t final_route_pc; + // internal routing goto instruction + uint32_t route_goto; + uint32_t error_route_goto; + uint32_t response_route_goto; + uint32_t final_route_goto; + + int ignore_body; + + struct uwsgi_transformation *transformations; + char *transformed_chunk; + size_t transformed_chunk_len; + + int is_raw; + +#ifdef UWSGI_SSL + SSL *ssl; +#endif + + // do not update avg_rt after request + int do_not_account_avg_rt; + // used for protocol parsers requiring EOF signaling + int proto_parser_eof; + + // 64bit range, deprecates size_t __range_from, __range_to + enum uwsgi_range range_parsed; + int64_t range_from; + int64_t range_to; + + char * if_range; + uint16_t if_range_len; + + // client address in a type-safe fashion; always use this over + // c_addr (which only exists to maintain binary compatibility in this + // struct) + union address { + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_un sun; + } client_addr; +}; + + +struct uwsgi_fmon { + char filename[0xff]; + int fd; + int id; + int registered; + uint8_t sig; +}; + +struct uwsgi_timer { + int value; + int fd; + int id; + int registered; + uint8_t sig; +}; + +struct uwsgi_signal_rb_timer { + int value; + int registered; + int iterations; + int iterations_done; + uint8_t sig; + struct uwsgi_rb_timer *uwsgi_rb_timer; +}; + +struct uwsgi_cheaper_algo { + + char *name; + int (*func) (int); + struct uwsgi_cheaper_algo *next; +}; + +struct uwsgi_emperor_scanner; + +struct uwsgi_imperial_monitor { + char *scheme; + void (*init) (struct uwsgi_emperor_scanner *); + void (*func) (struct uwsgi_emperor_scanner *); + struct uwsgi_imperial_monitor *next; +}; + +struct uwsgi_clock { + char *name; + time_t(*seconds) (void); + uint64_t(*microseconds) (void); + struct uwsgi_clock *next; +}; + +struct uwsgi_subscribe_slot; +struct uwsgi_stats_pusher; +struct uwsgi_stats_pusher_instance; + +#define UWSGI_PROTO_MIN_CHECK 4 +#define UWSGI_PROTO_MAX_CHECK 28 + +struct uwsgi_offload_engine; + +// these are the possible states of an instance +struct uwsgi_instance_status { + int gracefully_reloading; + int brutally_reloading; + int gracefully_destroying; + int brutally_destroying; + int chain_reloading; + int workers_reloading; + int is_cheap; + int is_cleaning; + int dying_for_need_app; +}; + +struct uwsgi_configurator { + char *name; + void (*func)(char *, char **); + struct uwsgi_configurator *next; +}; +struct uwsgi_configurator *uwsgi_register_configurator(char *, void (*)(char *, char **)); +void uwsgi_opt_load_config(char *, char *, void *); + +#define uwsgi_instance_is_dying (uwsgi.status.gracefully_destroying || uwsgi.status.brutally_destroying) +#define uwsgi_instance_is_reloading (uwsgi.status.gracefully_reloading || uwsgi.status.brutally_reloading) + +#define exit(x) uwsgi_exit(x) + +struct uwsgi_metric; + +struct uwsgi_logging_options { + int enabled; + int memory_report; + int zero; + int _4xx; + int _5xx; + int sendfile; + int ioerror; + uint32_t slow; + uint64_t big; + int log_x_forwarded_for; +}; + +struct uwsgi_harakiri_options { + int workers; + int spoolers; + int mules; +}; + +struct uwsgi_fsmon { + char *path; + int fd; + int id; + void *data; + void (*func)(struct uwsgi_fsmon *); + struct uwsgi_fsmon *next; +}; + +struct uwsgi_server { + + // store the machine hostname + char hostname[256]; + int hostname_len; + + // used to store the exit code for atexit hooks + int last_exit_code; + + int (*proto_hooks[UWSGI_PROTO_MAX_CHECK]) (struct wsgi_request *, char *, char *, uint16_t); + struct uwsgi_configurator *configurators; + + char **orig_argv; + char **argv; + int argc; + int max_procname; + int auto_procname; + char **environ; + char *procname_prefix; + char *procname_append; + char *procname_master; + char *procname; + + struct uwsgi_logging_options logging_options; + struct uwsgi_harakiri_options harakiri_options; + int socket_timeout; + int reaper; + int cgi_mode; + uint64_t max_requests; + uint64_t min_worker_lifetime; + uint64_t max_worker_lifetime; + + // daemontools-like envdir + struct uwsgi_string_list *envdirs; + + char *requested_clock; + struct uwsgi_clock *clocks; + struct uwsgi_clock *clock; + + char *empty; + + // quiet startup + int no_initial_output; + + struct uwsgi_instance_status status; + + struct uwsgi_string_list *get_list; + + // enable threads + int has_threads; + int no_threads_wait; + + // default app id + int default_app; + + char *logto2; + char *logformat; + int logformat_strftime; + int logformat_vectors; + struct uwsgi_logchunk *logchunks; + struct uwsgi_logchunk *registered_logchunks; + void (*logit) (struct wsgi_request *); + struct iovec **logvectors; + + // autoload plugins + int autoload; + struct uwsgi_string_list *plugins_dir; + struct uwsgi_string_list *blacklist; + struct uwsgi_string_list *whitelist; + char *blacklist_context; + char *whitelist_context; + + unsigned int reloads; + + // leave master running as root + int master_as_root; + // postpone privileges drop + int drop_after_init; + int drop_after_apps; + + int master_is_reforked; + + struct uwsgi_string_list *master_fifo; + int master_fifo_fd; + int master_fifo_slot; + + + // kill the stack on SIGTERM (instead of brutal reloading) + int die_on_term; + + // force the first gateway without a master + int force_gateway; + + // disable fd passing on unix socket + int no_fd_passing; + + // store the current time + time_t current_time; + + uint64_t master_cycles; + + int reuse_port; + int tcp_fast_open; + int tcp_fast_open_client; + + int enable_proxy_protocol; + + uint64_t fastcgi_modifier1; + uint64_t fastcgi_modifier2; + uint64_t http_modifier1; + uint64_t http_modifier2; + uint64_t https_modifier1; + uint64_t https_modifier2; + uint64_t scgi_modifier1; + uint64_t scgi_modifier2; + uint64_t raw_modifier1; + uint64_t raw_modifier2; + + // enable lazy mode + int lazy; + // enable lazy-apps mode + int lazy_apps; + // enable cheaper mode + int cheaper; + char *requested_cheaper_algo; + struct uwsgi_cheaper_algo *cheaper_algos; + int (*cheaper_algo) (int); + int cheaper_step; + uint64_t cheaper_overload; + // minimal number of running workers in cheaper mode + int cheaper_count; + int cheaper_initial; + // enable idle mode + int idle; + + // cheaper mode memory usage limits + uint64_t cheaper_rss_limit_soft; + uint64_t cheaper_rss_limit_hard; + + int cheaper_fifo_delta; + + // destroy the stack when idle + int die_on_idle; + + // store the screen session + char *screen_session; + + // true if run under the emperor + int has_emperor; + char *emperor_procname; + char *emperor_proxy; + int emperor_fd; + int emperor_fd_proxy; + int emperor_queue; + int emperor_nofollow; + int emperor_tyrant; + int emperor_tyrant_nofollow; + int emperor_fd_config; + int early_emperor; + int emperor_throttle; + int emperor_freq; + int emperor_max_throttle; + int emperor_magic_exec; + int emperor_heartbeat; + int emperor_curse_tolerance; + struct uwsgi_string_list *emperor_extra_extension; + // search for a file with the specified extension at the same level of the vassal file + char *emperor_on_demand_extension; + // bind to a unix socket on the specified directory named directory/vassal.socket + char *emperor_on_demand_directory; + // run a shell script passing the vassal as the only argument, the stdout is used as the socket + char *emperor_on_demand_exec; + + int disable_nuclear_blast; + + time_t next_heartbeat; + int heartbeat; + struct uwsgi_string_list *emperor; + struct uwsgi_imperial_monitor *emperor_monitors; + char *emperor_absolute_dir; + char *emperor_pidfile; + pid_t emperor_pid; + int emperor_broodlord; + int emperor_broodlord_count; + uint64_t emperor_broodlord_num; + char *emperor_stats; + int emperor_stats_fd; + struct uwsgi_string_list *vassals_templates; + struct uwsgi_string_list *vassals_includes; + struct uwsgi_string_list *vassals_templates_before; + struct uwsgi_string_list *vassals_includes_before; + struct uwsgi_string_list *vassals_set; + // true if loyal to the emperor + int loyal; + + // emperor hook (still in development) + char *vassals_start_hook; + char *vassals_stop_hook; + + struct uwsgi_string_list *additional_headers; + struct uwsgi_string_list *remove_headers; + struct uwsgi_string_list *collect_headers; + + // set cpu affinity + int cpu_affinity; + + int reload_mercy; + int worker_reload_mercy; + // map reloads to death + int exit_on_reload; + + // store options + int dirty_config; + int option_index; + int (*logic_opt) (char *, char *); + char *logic_opt_arg; + char *logic_opt_data; + int logic_opt_running; + int logic_opt_cycles; + struct uwsgi_option *options; + struct option *long_options; + char *short_options; + struct uwsgi_opt **exported_opts; + int exported_opts_cnt; + struct uwsgi_custom_option *custom_options; + + // dump the whole set of options + int dump_options; + // show ini representation of the current config + int show_config; + // enable strict mode (only registered options can be used) + int strict; + + // list loaded features + int cheaper_algo_list; +#ifdef UWSGI_ROUTING + int router_list; +#endif + int imperial_monitor_list; + int plugins_list; + int loggers_list; + int loop_list; + int clock_list; + int alarms_list; + + struct wsgi_request *wsgi_req; + + char *remap_modifier; + + // enable zerg mode + int *zerg; + char *zerg_server; + struct uwsgi_string_list *zerg_node; + int zerg_fallback; + int zerg_server_fd; + + // security + char *chroot; + gid_t gid; + uid_t uid; + char *uidname; + char *gidname; + int no_initgroups; + struct uwsgi_string_list *additional_gids; + +#ifdef UWSGI_CAP + cap_value_t *cap; + int cap_count; + cap_value_t *emperor_cap; + int emperor_cap_count; +#endif + +#ifdef __linux__ + int unshare; + int unshare2; + int emperor_clone; + char *pivot_root; + char *setns_socket; + struct uwsgi_string_list *setns_socket_skip; + char *setns; + int setns_socket_fd; + int setns_preopen; + int setns_fds[64]; + int setns_fds_count; +#endif + char *emperor_wrapper; + + int jailed; +#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__) + char *jail; + struct uwsgi_string_list *jail_ip4; +#ifdef AF_INET6 + struct uwsgi_string_list *jail_ip6; +#endif + struct uwsgi_string_list *jail2; + char *jidfile; + char *jail_attach; +#endif + int refork; + int refork_as_root; + int refork_post_jail; + + int ignore_sigpipe; + int ignore_write_errors; + uint64_t write_errors_tolerance; + int write_errors_exception_only; + int disable_write_exception; + + // still working on it + char *profiler; + + // the weight of the instance, used by various cluster/lb components + uint64_t weight; + int auto_weight; + + // mostly useless + char *mode; + + // binary patch the worker image + char *worker_exec; + char *worker_exec2; + + // this must be UN-shared + struct uwsgi_gateway_socket *gateway_sockets; + + + int ignore_script_name; + int manage_script_name; + int reload_on_exception; + int catch_exceptions; + struct uwsgi_string_list *reload_on_exception_type; + struct uwsgi_string_list *reload_on_exception_value; + struct uwsgi_string_list *reload_on_exception_repr; + + struct uwsgi_exception_handler *exception_handlers; + struct uwsgi_string_list *exception_handlers_instance; + struct uwsgi_thread *exception_handler_thread; + uint64_t exception_handler_msg_size; + + + int no_default_app; + // exit if no-app is loaded + int need_app; + + int forkbomb_delay; + + int logdate; + int log_micros; + char *log_strftime; + + int honour_stdin; + struct termios termios; + int restore_tc; + + // honour the HTTP Range header + int honour_range; + + // route all of the logs to the master process + int req_log_master; + int log_master; + char *log_master_buf; + size_t log_master_bufsize; + int log_master_stream; + int log_master_req_stream; + + int log_reopen; + int log_truncate; + uint64_t log_maxsize; + char *log_backupname; + + int original_log_fd; + int req_log_fd; + + // static file serving + int file_serve_mode; + int build_mime_dict; + + struct uwsgi_string_list *mime_file; + + struct uwsgi_hook *hooks; + + struct uwsgi_string_list *hook_touch; + + struct uwsgi_string_list *hook_asap; + struct uwsgi_string_list *hook_pre_jail; + struct uwsgi_string_list *hook_post_jail; + struct uwsgi_string_list *hook_in_jail; + struct uwsgi_string_list *hook_as_root; + struct uwsgi_string_list *hook_as_user; + struct uwsgi_string_list *hook_as_user_atexit; + struct uwsgi_string_list *hook_pre_app; + struct uwsgi_string_list *hook_post_app; + struct uwsgi_string_list *hook_accepting; + struct uwsgi_string_list *hook_accepting1; + struct uwsgi_string_list *hook_accepting_once; + struct uwsgi_string_list *hook_accepting1_once; + + struct uwsgi_string_list *hook_emperor_start; + struct uwsgi_string_list *hook_master_start; + + struct uwsgi_string_list *hook_emperor_stop; + struct uwsgi_string_list *hook_emperor_reload; + struct uwsgi_string_list *hook_emperor_lost; + + struct uwsgi_string_list *hook_as_vassal; + struct uwsgi_string_list *hook_as_emperor; + struct uwsgi_string_list *hook_as_mule; + struct uwsgi_string_list *hook_as_gateway; + + + struct uwsgi_string_list *exec_asap; + struct uwsgi_string_list *exec_pre_jail; + struct uwsgi_string_list *exec_post_jail; + struct uwsgi_string_list *exec_in_jail; + struct uwsgi_string_list *exec_as_root; + struct uwsgi_string_list *exec_as_user; + struct uwsgi_string_list *exec_as_user_atexit; + struct uwsgi_string_list *exec_pre_app; + struct uwsgi_string_list *exec_post_app; + + struct uwsgi_string_list *exec_as_vassal; + struct uwsgi_string_list *exec_as_emperor; + + struct uwsgi_string_list *call_asap; + struct uwsgi_string_list *call_pre_jail; + struct uwsgi_string_list *call_post_jail; + struct uwsgi_string_list *call_in_jail; + struct uwsgi_string_list *call_as_root; + struct uwsgi_string_list *call_as_user; + struct uwsgi_string_list *call_as_user_atexit; + struct uwsgi_string_list *call_pre_app; + struct uwsgi_string_list *call_post_app; + + struct uwsgi_string_list *call_as_vassal; + struct uwsgi_string_list *call_as_vassal1; + struct uwsgi_string_list *call_as_vassal3; + + struct uwsgi_string_list *call_as_emperor; + struct uwsgi_string_list *call_as_emperor1; + struct uwsgi_string_list *call_as_emperor2; + struct uwsgi_string_list *call_as_emperor4; + + struct uwsgi_string_list *mount_asap; + struct uwsgi_string_list *mount_pre_jail; + struct uwsgi_string_list *mount_post_jail; + struct uwsgi_string_list *mount_in_jail; + struct uwsgi_string_list *mount_as_root; + + struct uwsgi_string_list *mount_as_vassal; + struct uwsgi_string_list *mount_as_emperor; + + struct uwsgi_string_list *umount_asap; + struct uwsgi_string_list *umount_pre_jail; + struct uwsgi_string_list *umount_post_jail; + struct uwsgi_string_list *umount_in_jail; + struct uwsgi_string_list *umount_as_root; + + struct uwsgi_string_list *umount_as_vassal; + struct uwsgi_string_list *umount_as_emperor; + + struct uwsgi_string_list *after_request_hooks; + + struct uwsgi_string_list *wait_for_interface; + int wait_for_interface_timeout; + + char *privileged_binary_patch; + char *unprivileged_binary_patch; + char *privileged_binary_patch_arg; + char *unprivileged_binary_patch_arg; + + struct uwsgi_logger *loggers; + struct uwsgi_logger *choosen_logger; + struct uwsgi_logger *choosen_req_logger; + struct uwsgi_string_list *requested_logger; + struct uwsgi_string_list *requested_req_logger; + + struct uwsgi_log_encoder *log_encoders; + struct uwsgi_string_list *requested_log_encoders; + struct uwsgi_string_list *requested_log_req_encoders; + +#ifdef UWSGI_PCRE + int pcre_jit; + struct uwsgi_regexp_list *log_drain_rules; + struct uwsgi_regexp_list *log_filter_rules; + struct uwsgi_regexp_list *log_route; + struct uwsgi_regexp_list *log_req_route; +#endif + + int use_abort; + + int alarm_freq; + uint64_t alarm_msg_size; + struct uwsgi_string_list *alarm_list; + struct uwsgi_string_list *alarm_logs_list; + struct uwsgi_alarm_fd *alarm_fds; + struct uwsgi_string_list *alarm_fd_list; + struct uwsgi_string_list *alarm_segfault; + struct uwsgi_string_list *alarm_backlog; + struct uwsgi_alarm *alarms; + struct uwsgi_alarm_instance *alarm_instances; + struct uwsgi_alarm_log *alarm_logs; + struct uwsgi_thread *alarm_thread; + + int threaded_logger; + pthread_mutex_t threaded_logger_lock; + + int *safe_fds; + int safe_fds_cnt; + + int daemons_honour_stdin; + struct uwsgi_daemon *daemons; + int daemons_cnt; + +#ifdef UWSGI_SSL + char *subscriptions_sign_check_dir; + int subscriptions_sign_check_tolerance; + const EVP_MD *subscriptions_sign_check_md; + struct uwsgi_string_list *subscriptions_sign_skip_uid; +#endif + + struct uwsgi_string_list *subscriptions_credentials_check_dir; + int subscriptions_use_credentials; + + struct uwsgi_dyn_dict *static_maps; + struct uwsgi_dyn_dict *static_maps2; + struct uwsgi_dyn_dict *check_static; + struct uwsgi_dyn_dict *mimetypes; + struct uwsgi_string_list *static_skip_ext; + struct uwsgi_string_list *static_index; + struct uwsgi_string_list *static_safe; + + struct uwsgi_hash_algo *hash_algos; + int use_static_cache_paths; + char *static_cache_paths_name; + struct uwsgi_cache *static_cache_paths; + int cache_expire_freq; + int cache_report_freed_items; + int cache_no_expire; + uint64_t cache_max_items; + uint64_t cache_blocksize; + char *cache_store; + int cache_store_sync; + struct uwsgi_string_list *cache2; + int cache_setup; + int locking_setup; + int cache_use_last_modified; + + struct uwsgi_dyn_dict *static_expires_type; + struct uwsgi_dyn_dict *static_expires_type_mtime; + + struct uwsgi_dyn_dict *static_expires; + struct uwsgi_dyn_dict *static_expires_mtime; + + struct uwsgi_dyn_dict *static_expires_uri; + struct uwsgi_dyn_dict *static_expires_uri_mtime; + + struct uwsgi_dyn_dict *static_expires_path_info; + struct uwsgi_dyn_dict *static_expires_path_info_mtime; + + int static_gzip_all; + struct uwsgi_string_list *static_gzip_dir; + struct uwsgi_string_list *static_gzip_ext; +#ifdef UWSGI_PCRE + struct uwsgi_regexp_list *static_gzip; +#endif + + struct uwsgi_offload_engine *offload_engines; + struct uwsgi_offload_engine *offload_engine_sendfile; + struct uwsgi_offload_engine *offload_engine_transfer; + struct uwsgi_offload_engine *offload_engine_memory; + struct uwsgi_offload_engine *offload_engine_pipe; + int offload_threads; + int offload_threads_events; + struct uwsgi_thread **offload_thread; + + int check_static_docroot; + int disable_sendfile; + + char *daemonize; + char *daemonize2; + int do_not_change_umask; + char *logfile; + int logfile_chown; + + // enable vhost mode + int vhost; + int vhost_host; + + // async commodity + struct wsgi_request **async_waiting_fd_table; + struct wsgi_request **async_proto_fd_table; + struct uwsgi_async_request *async_runqueue; + struct uwsgi_async_request *async_runqueue_last; + + struct uwsgi_rbtree *rb_async_timeouts; + + int async_queue_unused_ptr; + struct wsgi_request **async_queue_unused; + + + // store rlimit + struct rlimit rl; + struct rlimit rl_nproc; + size_t limit_post; + + // set process priority + int prio; + + // funny reload systems + int force_get_memusage; + rlim_t reload_on_as; + rlim_t reload_on_rss; + rlim_t evil_reload_on_as; + rlim_t evil_reload_on_rss; + + struct uwsgi_string_list *reload_on_fd; + struct uwsgi_string_list *brutal_reload_on_fd; + + struct uwsgi_string_list *touch_reload; + struct uwsgi_string_list *touch_chain_reload; + struct uwsgi_string_list *touch_workers_reload; + struct uwsgi_string_list *touch_gracefully_stop; + struct uwsgi_string_list *touch_logrotate; + struct uwsgi_string_list *touch_logreopen; + struct uwsgi_string_list *touch_exec; + struct uwsgi_string_list *touch_signal; + + struct uwsgi_string_list *fs_reload; + struct uwsgi_string_list *fs_brutal_reload; + struct uwsgi_string_list *fs_signal; + + struct uwsgi_fsmon *fsmon; + + struct uwsgi_string_list *signal_timers; + struct uwsgi_string_list *rb_signal_timers; + + struct uwsgi_string_list *mountpoints_check; + + int propagate_touch; + + // enable grunt mode + int grunt; + + // store the binary path + char *binary_path; + + int is_a_reload; + + + char *udp_socket; + + int multicast_ttl; + int multicast_loop; + char *multicast_group; + + struct uwsgi_spooler *spoolers; + int spooler_numproc; + struct uwsgi_spooler *i_am_a_spooler; + char *spooler_chdir; + int spooler_max_tasks; + int spooler_ordered; + int spooler_quiet; + int spooler_frequency; + + int snmp; + char *snmp_addr; + char *snmp_community; + struct uwsgi_lock_item *snmp_lock; + int snmp_fd; + + int udp_fd; + + uint16_t buffer_size; + int signal_bufsize; + + // post buffering + size_t post_buffering; + int post_buffering_harakiri; + size_t post_buffering_bufsize; + size_t body_read_warning; + + int master_process; + int master_queue; + int master_interval; + + // mainly iseful for broodlord mode + int vassal_sos_backlog; + + int no_defer_accept; + int so_keepalive; + int so_send_timeout; + uint64_t so_sndbuf; + uint64_t so_rcvbuf; + + int page_size; + int cpus; + + char *pidfile; + char *pidfile2; + + char *flock2; + char *flock_wait2; + + int backtrace_depth; + + int harakiri_verbose; + int harakiri_no_arh; + + int magic_table_first_round; + char *magic_table[256]; + + int numproc; + int async; + int async_running; + int async_queue; + int async_nevents; + + time_t async_queue_is_full; + + int max_vars; + int vec_size; + + // shared area + struct uwsgi_string_list *sharedareas_list; + int sharedareas_cnt; + struct uwsgi_sharedarea **sharedareas; + + // avoid thundering herd in threaded modes + pthread_mutex_t thunder_mutex; + pthread_mutex_t six_feet_under_lock; + pthread_mutex_t lock_static; + + int use_thunder_lock; + struct uwsgi_lock_item *the_thunder_lock; + + /* the list of workers */ + struct uwsgi_worker *workers; + int max_apps; + + /* the list of mules */ + struct uwsgi_string_list *mules_patches; + struct uwsgi_mule *mules; + struct uwsgi_string_list *farms_list; + struct uwsgi_farm *farms; + int mule_msg_size; + + pid_t mypid; + int mywid; + + int muleid; + int mules_cnt; + int farms_cnt; + + rlim_t requested_max_fd; + rlim_t max_fd; + + struct timeval start_tv; + + int abstract_socket; +#ifdef __linux__ + int freebind; +#endif + + int chmod_socket; + char *chown_socket; + mode_t chmod_socket_value; + mode_t chmod_logfile_value; + int listen_queue; + + char *fallback_config; + +#ifdef UWSGI_ROUTING + struct uwsgi_router *routers; + struct uwsgi_route *routes; + struct uwsgi_route *final_routes; + struct uwsgi_route *error_routes; + struct uwsgi_route *response_routes; + struct uwsgi_route_condition *route_conditions; + struct uwsgi_route_var *route_vars; +#endif + + struct uwsgi_string_list *error_page_403; + struct uwsgi_string_list *error_page_404; + struct uwsgi_string_list *error_page_500; + + int single_interpreter; + + struct uwsgi_shared *shared; + + + int no_orphans; + int skip_zero; + int skip_atexit; + + char *force_cwd; + char *chdir; + char *chdir2; + struct uwsgi_string_list *binsh; + + int vacuum; + int no_server; + int command_mode; + + int xml_round2; + + char *cwd; + + // conditional logging + int log_slow_requests; + int log_zero_headers; + int log_empty_body; + int log_high_memory; + +#ifdef __linux__ + struct uwsgi_string_list *cgroup; + struct uwsgi_string_list *cgroup_opt; + char *cgroup_dir_mode; + char *ns; + char *ns_net; + struct uwsgi_string_list *ns_keep_mount; +#endif + struct uwsgi_string_list *file_write_list; + + char *protocol; + + int signal_socket; + int my_signal_socket; + + struct uwsgi_protocol *protocols; + struct uwsgi_socket *sockets; + struct uwsgi_socket *shared_sockets; + int is_et; + + struct uwsgi_string_list *map_socket; + + struct uwsgi_cron *crons; + time_t cron_harakiri; + + time_t respawn_delta; + + struct uwsgi_string_list *mounts; + + int cores; + + int threads; + pthread_attr_t threads_attr; + size_t threads_stacksize; + + //this key old the u_request structure per core / thread + pthread_key_t tur_key; + + + struct wsgi_request *(*current_wsgi_req) (void); + + void (*notify) (char *); + void (*notify_ready) (void); + int notification_fd; + void *notification_object; + + // usedby suspend/resume loops + void (*schedule_to_main) (struct wsgi_request *); + void (*schedule_to_req) (void); + void (*schedule_fix) (struct wsgi_request *); + + void (*gbcw_hook) (void); + + int close_on_exec; + int close_on_exec2; + + int tcp_nodelay; + + char *loop; + struct uwsgi_loop *loops; + + struct uwsgi_plugin *p[256]; + struct uwsgi_plugin *gp[MAX_GENERIC_PLUGINS]; + int gp_cnt; + + char *allowed_modifiers; + + char *upload_progress; + + struct uwsgi_lock_item *registered_locks; + struct uwsgi_lock_ops lock_ops; + char *lock_engine; + char *ftok; + char *lock_id; + size_t lock_size; + size_t rwlock_size; + + struct uwsgi_string_list *add_cache_item; + struct uwsgi_string_list *load_file_in_cache; +#ifdef UWSGI_ZLIB + struct uwsgi_string_list *load_file_in_cache_gzip; +#endif + char *use_check_cache; + struct uwsgi_cache *check_cache; + struct uwsgi_cache *caches; + + struct uwsgi_string_list *cache_udp_server; + struct uwsgi_string_list *cache_udp_node; + + char *cache_sync; + + // the stats server + char *stats; + int stats_fd; + int stats_http; + int stats_minified; + struct uwsgi_string_list *requested_stats_pushers; + struct uwsgi_stats_pusher *stats_pushers; + struct uwsgi_stats_pusher_instance *stats_pusher_instances; + int stats_pusher_default_freq; + + uint64_t queue_size; + uint64_t queue_blocksize; + void *queue; + struct uwsgi_queue_header *queue_header; + char *queue_store; + size_t queue_filesize; + int queue_store_sync; + + + int locks; + int persistent_ipcsem; + + struct uwsgi_lock_item *queue_lock; + struct uwsgi_lock_item **user_lock; + struct uwsgi_lock_item *signal_table_lock; + struct uwsgi_lock_item *fmon_table_lock; + struct uwsgi_lock_item *timer_table_lock; + struct uwsgi_lock_item *rb_timer_table_lock; + struct uwsgi_lock_item *cron_table_lock; + struct uwsgi_lock_item *rpc_table_lock; + struct uwsgi_lock_item *sa_lock; + struct uwsgi_lock_item *metrics_lock; + + // rpc + uint64_t rpc_max; + struct uwsgi_rpc *rpc_table; + + // subscription client + int subscriptions_blocked; + int subscribe_freq; + int subscription_tolerance; + int unsubscribe_on_graceful_reload; + struct uwsgi_string_list *subscriptions; + struct uwsgi_string_list *subscriptions2; + + struct uwsgi_subscribe_node *(*subscription_algo) (struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_node *); + int subscription_dotsplit; + + int never_swap; + +#ifdef UWSGI_SSL + int ssl_initialized; + int ssl_verbose; + char *ssl_sessions_use_cache; + int ssl_sessions_timeout; + struct uwsgi_cache *ssl_sessions_cache; + char *ssl_tmp_dir; +#ifdef UWSGI_PCRE + struct uwsgi_regexp_list *sni_regexp; +#endif + struct uwsgi_string_list *sni; + char *sni_dir; + char *sni_dir_ciphers; +#endif + +#ifdef UWSGI_SSL + struct uwsgi_legion *legions; + struct uwsgi_legion_action *legion_actions; + int legion_queue; + int legion_freq; + int legion_tolerance; + int legion_skew_tolerance; + uint16_t legion_scroll_max_size; + uint64_t legion_scroll_list_max_size; + int legion_death_on_lord_error; +#endif + +#ifdef __linux__ +#ifdef MADV_MERGEABLE + int linux_ksm; + int ksm_buffer_size; + char *ksm_mappings_last; + char *ksm_mappings_current; + size_t ksm_mappings_last_size; + size_t ksm_mappings_current_size; +#endif +#endif + + struct uwsgi_buffer *websockets_ping; + struct uwsgi_buffer *websockets_pong; + int websockets_ping_freq; + int websockets_pong_tolerance; + uint64_t websockets_max_size; + + int chunked_input_timeout; + uint64_t chunked_input_limit; + + struct uwsgi_metric *metrics; + struct uwsgi_metric_collector *metric_collectors; + int has_metrics; + char *metrics_dir; + int metrics_dir_restore; + uint64_t metrics_cnt; + struct uwsgi_string_list *additional_metrics; + struct uwsgi_string_list *metrics_threshold; + + int (*wait_write_hook) (int, int); + int (*wait_read_hook) (int, int); + int (*wait_milliseconds_hook) (int); + int (*wait_read2_hook) (int, int, int, int *); + + struct uwsgi_string_list *schemes; + + // inject text files (useful for advanced templating) + struct uwsgi_string_list *inject_before; + struct uwsgi_string_list *inject_after; + + // this is a unix socket receiving external notifications (like subscription replies) + char *notify_socket; + int notify_socket_fd; + char *subscription_notify_socket; + + //uWSGI 2.0.5 + + int mule_reload_mercy; + int alarm_cheap; + + int emperor_no_blacklist; + int metrics_no_cores; + int stats_no_cores; + int stats_no_metrics; + + // uWSGI 2.0.7 + int vassal_sos; + + // uWSGI 2.0.8 + struct uwsgi_string_list *wait_for_fs; + struct uwsgi_string_list *wait_for_dir; + struct uwsgi_string_list *wait_for_file; + int wait_for_fs_timeout; + struct uwsgi_string_list *wait_for_mountpoint; +#ifdef UWSGI_SSL + int sslv3; + struct uwsgi_string_list *ssl_options; +#endif + struct uwsgi_string_list *hook_post_fork; + + // uWSGI 2.0.9 + char *subscribe_with_modifier1; + struct uwsgi_string_list *pull_headers; + + // uWSGI 2.0.10 + struct uwsgi_string_list *emperor_wrapper_override; + struct uwsgi_string_list *emperor_wrapper_fallback; + + // uWSGI 2.0.11 + struct uwsgi_string_list *wait_for_socket; + int wait_for_socket_timeout; + int mem_collector_freq; + + // uWSGI 2.0.14 + struct uwsgi_string_list *touch_mules_reload; + struct uwsgi_string_list *touch_spoolers_reload; + int spooler_reload_mercy; + + int skip_atexit_teardown; + + // uWSGI 2.1 backport + int new_argc; + char **new_argv; + + // uWSGI 2.0.16 +#ifdef UWSGI_SSL + int ssl_verify_depth; +#endif + + size_t response_header_limit; + char *safe_pidfile; + char *safe_pidfile2; + + // uWSGI 2.0.17 + int shutdown_sockets; + +#ifdef UWSGI_SSL + int tlsv1; +#endif +}; + +struct uwsgi_rpc { + char name[UMAX8]; + void *func; + uint8_t args; + uint8_t shared; + struct uwsgi_plugin *plugin; +}; + +struct uwsgi_signal_entry { + int wid; + uint8_t modifier1; + char receiver[64]; + void *handler; +}; + +/* +they are here for backwards compatibility +*/ +#define SNMP_COUNTER32 0x41 +#define SNMP_GAUGE 0x42 +#define SNMP_COUNTER64 0x46 + +struct uwsgi_snmp_custom_value { + uint8_t type; + uint64_t val; +}; + +int uwsgi_setup_snmp(void); + +struct uwsgi_snmp_server_value { + uint8_t type; + uint64_t *val; +}; + +struct uwsgi_cron { + + int minute; + int hour; + int day; + int month; + int week; + + time_t last_job; + uint8_t sig; + + char *command; + void (*func)(struct uwsgi_cron *, time_t); + + time_t started_at; + + // next harakiri timestamp + time_t harakiri; + // number of seconds to wait before calling harakiri on cron + int mercy; + + uint8_t unique; + pid_t pid; + + struct uwsgi_cron *next; + +#ifdef UWSGI_SSL + char *legion; +#endif +}; + +struct uwsgi_shared { + + //vga 80 x25 specific ! + char warning_message[81]; + + off_t logsize; + + char snmp_community[72 + 1]; + struct uwsgi_snmp_server_value snmp_gvalue[100]; + struct uwsgi_snmp_custom_value snmp_value[100]; + + int worker_signal_pipe[2]; + int spooler_frequency; + int spooler_signal_pipe[2]; + int mule_signal_pipe[2]; + int mule_queue_pipe[2]; + + // 256 items * (uwsgi.numproc + 1) + struct uwsgi_signal_entry *signal_table; + + struct uwsgi_fmon files_monitored[64]; + int files_monitored_cnt; + + struct uwsgi_timer timers[MAX_TIMERS]; + int timers_cnt; + + struct uwsgi_signal_rb_timer rb_timers[MAX_TIMERS]; + int rb_timers_cnt; + + uint64_t *rpc_count; + + int worker_log_pipe[2]; + // used for request logging + int worker_req_log_pipe[2]; + + uint64_t load; + uint64_t max_load; + struct uwsgi_cron cron[MAX_CRONS]; + int cron_cnt; + + uint64_t backlog; + uint64_t backlog_errors; + + // gateways + struct uwsgi_gateway gateways[MAX_GATEWAYS]; + int gateways_cnt; + time_t gateways_harakiri[MAX_GATEWAYS]; + + uint64_t routed_signals; + uint64_t unrouted_signals; + + uint64_t busy_workers; + uint64_t idle_workers; + uint64_t overloaded; + + int ready; +}; + +struct uwsgi_core { + + //time_t harakiri; + + uint64_t requests; + uint64_t failed_requests; + uint64_t static_requests; + uint64_t routed_requests; + uint64_t offloaded_requests; + + uint64_t write_errors; + uint64_t read_errors; + uint64_t exceptions; + + pthread_t thread_id; + + int offload_rr; + + // one ts-perapp + void **ts; + + int in_request; + + char *buffer; + struct iovec *hvec; + char *post_buf; + + struct wsgi_request req; +}; + +struct uwsgi_worker { + int id; + pid_t pid; + + uint64_t status; + + time_t last_spawn; + uint64_t respawn_count; + + uint64_t requests; + uint64_t delta_requests; + uint64_t failed_requests; + + time_t harakiri; + time_t user_harakiri; + uint64_t harakiri_count; + int pending_harakiri; + + uint64_t vsz_size; + uint64_t rss_size; + + uint64_t running_time; + + int manage_next_request; + + int destroy; + + int apps_cnt; + struct uwsgi_app *apps; + + uint64_t tx; + + int hijacked; + uint64_t hijacked_count; + int cheaped; + int suspended; + int sig; + uint8_t signum; + + time_t cursed_at; + time_t no_mercy_at; + + // signals managed by this worker + uint64_t signals; + + int signal_pipe[2]; + + uint64_t avg_response_time; + + struct uwsgi_core *cores; + + int accepting; + + char name[0xff]; + + int shutdown_sockets; +}; + + +struct uwsgi_mule { + int id; + pid_t pid; + + int signal_pipe[2]; + int queue_pipe[2]; + + time_t last_spawn; + uint64_t respawn_count; + + char *patch; + + // signals managed by this mule + uint64_t signals; + int sig; + uint8_t signum; + + time_t harakiri; + time_t user_harakiri; + + char name[0xff]; + + time_t cursed_at; + time_t no_mercy_at; +}; + +struct uwsgi_mule_farm { + struct uwsgi_mule *mule; + struct uwsgi_mule_farm *next; +}; + +struct uwsgi_farm { + int id; + char name[0xff]; + + int signal_pipe[2]; + int queue_pipe[2]; + + struct uwsgi_mule_farm *mules; + +}; + + + +char *uwsgi_get_cwd(void); + +void warn_pipe(void); +void what_i_am_doing(void); +void goodbye_cruel_world(void); +void gracefully_kill(int); +void reap_them_all(int); +void kill_them_all(int); +void grace_them_all(int); +void end_me(int); +int bind_to_unix(char *, int, int, int); +int bind_to_tcp(char *, int, char *); +int bind_to_udp(char *, int, int); +int bind_to_unix_dgram(char *); +int timed_connect(struct pollfd *, const struct sockaddr *, int, int, int); +int uwsgi_connect(char *, int, int); +int uwsgi_connect_udp(char *); +int uwsgi_connectn(char *, uint16_t, int, int); + +void daemonize(char *); +void logto(char *); + +void log_request(struct wsgi_request *); +void get_memusage(uint64_t *, uint64_t *); +void harakiri(void); + +void stats(int); + +#ifdef UWSGI_XML +void uwsgi_xml_config(char *, struct wsgi_request *, char *[]); +#endif + +void uwsgi_500(struct wsgi_request *); +void uwsgi_403(struct wsgi_request *); +void uwsgi_404(struct wsgi_request *); +void uwsgi_405(struct wsgi_request *); +void uwsgi_redirect_to_slash(struct wsgi_request *); + +void manage_snmp(int, uint8_t *, int, struct sockaddr_in *); +void snmp_init(void); + +void uwsgi_master_manage_snmp(int); + +char *uwsgi_spool_request(struct wsgi_request *, char *, size_t, char *, size_t); +void spooler(struct uwsgi_spooler *); +pid_t spooler_start(struct uwsgi_spooler *); + +int uwsgi_spooler_read_header(char *, int, struct uwsgi_header *); +int uwsgi_spooler_read_content(int, char *, char **, size_t *, struct uwsgi_header *, struct stat *); + +#if defined(_GNU_SOURCE) || defined(__UCLIBC__) +#define uwsgi_versionsort versionsort +#else +int uwsgi_versionsort(const struct dirent **da, const struct dirent **db); +#endif + +void uwsgi_curse(int, int); +void uwsgi_curse_mule(int, int); +void uwsgi_destroy_processes(void); + +void set_harakiri(int); +void set_user_harakiri(int); +void set_mule_harakiri(int); +void set_spooler_harakiri(int); +void inc_harakiri(int); + +#ifdef __BIG_ENDIAN__ +uint16_t uwsgi_swap16(uint16_t); +uint32_t uwsgi_swap32(uint32_t); +uint64_t uwsgi_swap64(uint64_t); +#endif + +int uwsgi_parse_request(int, struct wsgi_request *, int); +int uwsgi_parse_vars(struct wsgi_request *); + +int uwsgi_enqueue_message(char *, int, uint8_t, uint8_t, char *, int, int); + +void manage_opt(int, char *); + +int uwsgi_ping_node(int, struct wsgi_request *); + +void uwsgi_async_init(void); +void async_loop(); +struct wsgi_request *find_first_available_wsgi_req(void); +struct wsgi_request *find_first_accepting_wsgi_req(void); +struct wsgi_request *find_wsgi_req_by_fd(int); +struct wsgi_request *find_wsgi_req_by_id(int); +void async_schedule_to_req_green(void); +void async_schedule_to_req(void); + +int async_add_fd_write(struct wsgi_request *, int, int); +int async_add_fd_read(struct wsgi_request *, int, int); +void async_reset_request(struct wsgi_request *); + +struct wsgi_request *next_wsgi_req(struct wsgi_request *); + + +void async_add_timeout(struct wsgi_request *, int); + +void uwsgi_as_root(void); + +void uwsgi_close_request(struct wsgi_request *); + +void wsgi_req_setup(struct wsgi_request *, int, struct uwsgi_socket *); +int wsgi_req_recv(int, struct wsgi_request *); +int wsgi_req_async_recv(struct wsgi_request *); +int wsgi_req_accept(int, struct wsgi_request *); +int wsgi_req_simple_accept(struct wsgi_request *, int); + +#define current_wsgi_req() (*uwsgi.current_wsgi_req)() + +void sanitize_args(void); + +void env_to_arg(char *, char *); +void parse_sys_envs(char **); + +void uwsgi_log(const char *, ...); +void uwsgi_log_verbose(const char *, ...); +void uwsgi_logfile_write(const char *, ...); + + +void *uwsgi_load_plugin(int, char *, char *); + +int unconfigured_hook(struct wsgi_request *); + +void uwsgi_ini_config(char *, char *[]); + +#ifdef UWSGI_YAML +void uwsgi_yaml_config(char *, char *[]); +#endif + +#ifdef UWSGI_JSON +void uwsgi_json_config(char *, char *[]); +#endif + +int uwsgi_strncmp(char *, int, char *, int); +int uwsgi_strnicmp(char *, int, char *, int); +int uwsgi_startswith(char *, char *, int); + + +char *uwsgi_concat(int, ...); +char *uwsgi_concatn(int, ...); +char *uwsgi_concat2(char *, char *); +char *uwsgi_concat2n(char *, int, char *, int); +char *uwsgi_concat2nn(char *, int, char *, int, int *); +char *uwsgi_concat3(char *, char *, char *); +char *uwsgi_concat3n(char *, int, char *, int, char *, int); +char *uwsgi_concat4(char *, char *, char *, char *); +char *uwsgi_concat4n(char *, int, char *, int, char *, int, char *, int); + + +int uwsgi_get_app_id(struct wsgi_request *, char *, uint16_t, int); +char *uwsgi_strncopy(char *, int); + +int master_loop(char **, char **); + +int find_worker_id(pid_t); + + +void simple_loop(); +void *simple_loop_run(void *); + +int uwsgi_count_options(struct uwsgi_option *); + +struct wsgi_request *simple_current_wsgi_req(void); +struct wsgi_request *threaded_current_wsgi_req(void); + +void build_options(void); + +int uwsgi_postbuffer_do_in_disk(struct wsgi_request *); +int uwsgi_postbuffer_do_in_mem(struct wsgi_request *); + +void uwsgi_register_loop(char *, void (*)(void)); +void *uwsgi_get_loop(char *); + +void add_exported_option(char *, char *, int); +void add_exported_option_do(char *, char *, int, int); + +ssize_t uwsgi_send_empty_pkt(int, char *, uint8_t, uint8_t); + +int uwsgi_waitfd_event(int, int, int); +#define uwsgi_waitfd(a, b) uwsgi_waitfd_event(a, b, POLLIN) +#define uwsgi_waitfd_write(a, b) uwsgi_waitfd_event(a, b, POLLOUT) + +int uwsgi_hooked_parse_dict_dgram(int, char *, size_t, uint8_t, uint8_t, void (*)(char *, uint16_t, char *, uint16_t, void *), void *); +int uwsgi_hooked_parse(char *, size_t, void (*)(char *, uint16_t, char *, uint16_t, void *), void *); +int uwsgi_hooked_parse_array(char *, size_t, void (*) (uint16_t, char *, uint16_t, void *), void *); + +int uwsgi_get_dgram(int, struct wsgi_request *); + +int uwsgi_string_sendto(int, uint8_t, uint8_t, struct sockaddr *, socklen_t, char *, size_t); + +void uwsgi_stdin_sendto(char *, uint8_t, uint8_t); + +char *generate_socket_name(char *); + +#define UMIN(a,b) ((a)>(b)?(b):(a)) +#define UMAX(a,b) ((a)<(b)?(b):(a)) + +ssize_t uwsgi_send_message(int, uint8_t, uint8_t, char *, uint16_t, int, ssize_t, int); + +int uwsgi_cache_set2(struct uwsgi_cache *, char *, uint16_t, char *, uint64_t, uint64_t, uint64_t); +int uwsgi_cache_del2(struct uwsgi_cache *, char *, uint16_t, uint64_t, uint16_t); +char *uwsgi_cache_get2(struct uwsgi_cache *, char *, uint16_t, uint64_t *); +char *uwsgi_cache_get3(struct uwsgi_cache *, char *, uint16_t, uint64_t *, uint64_t *); +char *uwsgi_cache_get4(struct uwsgi_cache *, char *, uint16_t, uint64_t *, uint64_t *); +uint32_t uwsgi_cache_exists2(struct uwsgi_cache *, char *, uint16_t); +struct uwsgi_cache *uwsgi_cache_create(char *); +struct uwsgi_cache *uwsgi_cache_by_name(char *); +struct uwsgi_cache *uwsgi_cache_by_namelen(char *, uint16_t); +void uwsgi_cache_create_all(void); +void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *); +void uwsgi_cache_setup_nodes(struct uwsgi_cache *); +int64_t uwsgi_cache_num2(struct uwsgi_cache *, char *, uint16_t); + +void uwsgi_cache_sync_all(void); +void uwsgi_cache_start_sweepers(void); +void uwsgi_cache_start_sync_servers(void); + + +void *uwsgi_malloc(size_t); +void *uwsgi_calloc(size_t); + + +int event_queue_init(void); +void *event_queue_alloc(int); +int event_queue_add_fd_read(int, int); +int event_queue_add_fd_write(int, int); +int event_queue_del_fd(int, int, int); +int event_queue_wait(int, int, int *); +int event_queue_wait_multi(int, int, void *, int); +int event_queue_interesting_fd(void *, int); +int event_queue_interesting_fd_has_error(void *, int); +int event_queue_fd_write_to_read(int, int); +int event_queue_fd_read_to_write(int, int); +int event_queue_fd_readwrite_to_read(int, int); +int event_queue_fd_readwrite_to_write(int, int); +int event_queue_fd_read_to_readwrite(int, int); +int event_queue_fd_write_to_readwrite(int, int); +int event_queue_interesting_fd_is_read(void *, int); +int event_queue_interesting_fd_is_write(void *, int); + +int event_queue_add_timer(int, int *, int); +struct uwsgi_timer *event_queue_ack_timer(int); + +int event_queue_add_file_monitor(int, char *, int *); +struct uwsgi_fmon *event_queue_ack_file_monitor(int, int); + + +int uwsgi_register_signal(uint8_t, char *, void *, uint8_t); +int uwsgi_add_file_monitor(uint8_t, char *); +int uwsgi_add_timer(uint8_t, int); +int uwsgi_signal_add_rb_timer(uint8_t, int, int); +int uwsgi_signal_handler(uint8_t); + +void uwsgi_route_signal(uint8_t); + +int uwsgi_start(void *); + +int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *); +uint64_t uwsgi_rpc(char *, uint8_t, char **, uint16_t *, char **); +char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint64_t *); +void uwsgi_rpc_init(void); + +char *uwsgi_cheap_string(char *, int); + +int uwsgi_parse_array(char *, uint16_t, char **, uint16_t *, uint8_t *); + + +struct uwsgi_gateway *register_gateway(char *, void (*)(int, void *), void *); +void gateway_respawn(int); + +void uwsgi_gateway_go_cheap(char *, int, int *); + +char *uwsgi_open_and_read(char *, size_t *, int, char *[]); +char *uwsgi_get_last_char(char *, char); +char *uwsgi_get_last_charn(char *, size_t, char); + +void uwsgi_spawn_daemon(struct uwsgi_daemon *); +void uwsgi_detach_daemons(); + +void emperor_loop(void); +char *uwsgi_num2str(int); +char *uwsgi_float2str(float); +char *uwsgi_64bit2str(int64_t); + +char *magic_sub(char *, size_t, size_t *, char *[]); +void init_magic_table(char *[]); + +char *uwsgi_req_append(struct wsgi_request *, char *, uint16_t, char *, uint16_t); +int uwsgi_req_append_path_info_with_index(struct wsgi_request *, char *, uint16_t); +int is_unix(char *, int); +int is_a_number(char *); + +char *uwsgi_resolve_ip(char *); + +void uwsgi_init_queue(void); +char *uwsgi_queue_get(uint64_t, uint64_t *); +char *uwsgi_queue_pull(uint64_t *); +int uwsgi_queue_push(char *, uint64_t); +char *uwsgi_queue_pop(uint64_t *); +int uwsgi_queue_set(uint64_t, char *, uint64_t); + + +struct uwsgi_subscribe_req { + char *key; + uint16_t keylen; + + char *address; + uint16_t address_len; + + char *auth; + uint16_t auth_len; + + uint8_t modifier1; + uint8_t modifier2; + + uint64_t cores; + uint64_t load; + uint64_t weight; + char *sign; + uint16_t sign_len; + + time_t unix_check; + + char *base; + uint16_t base_len; + + char *sni_key; + uint16_t sni_key_len; + + char *sni_crt; + uint16_t sni_crt_len; + + char *sni_ca; + uint16_t sni_ca_len; + + pid_t pid; + uid_t uid; + gid_t gid; + + char *notify; + uint16_t notify_len; +}; + +void uwsgi_nuclear_blast(); + +void uwsgi_unix_signal(int, void (*)(int)); + +char *uwsgi_get_exported_opt(char *); +char *uwsgi_manage_placeholder(char *); + +int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int); +int uwsgi_cron_task_needs_execution(struct tm *, int, int, int, int, int); + +char *uwsgi_get_optname_by_index(int); + +int uwsgi_list_has_num(char *, int); + +int uwsgi_list_has_str(char *, char *); + +void uwsgi_cache_fix(struct uwsgi_cache *); + +struct uwsgi_async_request { + + struct wsgi_request *wsgi_req; + struct uwsgi_async_request *prev; + struct uwsgi_async_request *next; +}; + +int event_queue_read(void); +int event_queue_write(void); + +void uwsgi_help(char *, char *, void *); +void uwsgi_print_sym(char *, char *, void *); + +int uwsgi_str2_num(char *); +int uwsgi_str3_num(char *); +int uwsgi_str4_num(char *); + +#ifdef __linux__ +#if !defined(__ia64__) +void linux_namespace_start(void *); +void linux_namespace_jail(void); +#endif +void uwsgi_master_manage_setns(int); +void uwsgi_setns(char *); +void uwsgi_setns_preopen(void); +#endif + + +int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *); +char *uwsgi_amqp_consume(int, uint64_t *, char **); + +int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, int); +int uwsgi_starts_with(char *, int, char *, int); +int uwsgi_static_want_gzip(struct wsgi_request *, char *, size_t *, struct stat *); + +#ifdef __sun__ +time_t timegm(struct tm *); +#endif + +uint64_t uwsgi_str_num(char *, int); +size_t uwsgi_str_occurence(char *, size_t, char); + +int uwsgi_proto_base_write(struct wsgi_request *, char *, size_t); +int uwsgi_proto_base_writev(struct wsgi_request *, struct iovec *, size_t *); +#ifdef UWSGI_SSL +int uwsgi_proto_ssl_write(struct wsgi_request *, char *, size_t); +#endif +int uwsgi_proto_base_write_header(struct wsgi_request *, char *, size_t); +ssize_t uwsgi_proto_base_read_body(struct wsgi_request *, char *, size_t); +ssize_t uwsgi_proto_noop_read_body(struct wsgi_request *, char *, size_t); +#ifdef UWSGI_SSL +ssize_t uwsgi_proto_ssl_read_body(struct wsgi_request *, char *, size_t); +#endif + + +int uwsgi_proto_base_accept(struct wsgi_request *, int); +void uwsgi_proto_base_close(struct wsgi_request *); +#ifdef UWSGI_SSL +int uwsgi_proto_ssl_accept(struct wsgi_request *, int); +void uwsgi_proto_ssl_close(struct wsgi_request *); +#endif +uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t); +uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t); + +// protocols +void uwsgi_proto_uwsgi_setup(struct uwsgi_socket *); +void uwsgi_proto_puwsgi_setup(struct uwsgi_socket *); +void uwsgi_proto_raw_setup(struct uwsgi_socket *); +void uwsgi_proto_http_setup(struct uwsgi_socket *); +void uwsgi_proto_http11_setup(struct uwsgi_socket *); +#ifdef UWSGI_SSL +void uwsgi_proto_https_setup(struct uwsgi_socket *); +void uwsgi_proto_suwsgi_setup(struct uwsgi_socket *); +#endif +#ifdef UWSGI_ZEROMQ +void uwsgi_proto_zmq_setup(struct uwsgi_socket *); +#endif +void uwsgi_proto_fastcgi_setup(struct uwsgi_socket *); +void uwsgi_proto_fastcgi_nph_setup(struct uwsgi_socket *); + +void uwsgi_proto_scgi_setup(struct uwsgi_socket *); +void uwsgi_proto_scgi_nph_setup(struct uwsgi_socket *); + +int uwsgi_num2str2(int, char *); + + +void uwsgi_add_socket_from_fd(struct uwsgi_socket *, int); + + +char *uwsgi_split3(char *, size_t, char, char **, size_t *, char **, size_t *, char **, size_t *); +char *uwsgi_split4(char *, size_t, char, char **, size_t *, char **, size_t *, char **, size_t *, char **, size_t *); +char *uwsgi_netstring(char *, size_t, char **, size_t *); + +char *uwsgi_str_split_nget(char *, size_t, char, size_t, size_t *); + +int uwsgi_get_socket_num(struct uwsgi_socket *); +struct uwsgi_socket *uwsgi_new_socket(char *); +struct uwsgi_socket *uwsgi_new_shared_socket(char *); +struct uwsgi_socket *uwsgi_del_socket(struct uwsgi_socket *); + +void uwsgi_close_all_sockets(void); +void uwsgi_shutdown_all_sockets(void); +void uwsgi_close_all_unshared_sockets(void); + +struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **, char *); +#ifdef UWSGI_PCRE +struct uwsgi_regexp_list *uwsgi_regexp_custom_new_list(struct uwsgi_regexp_list **, char *, char *); +#define uwsgi_regexp_new_list(x, y) uwsgi_regexp_custom_new_list(x, y, NULL); +#endif + +void uwsgi_string_del_list(struct uwsgi_string_list **, struct uwsgi_string_list *); + +void uwsgi_init_all_apps(void); +void uwsgi_init_worker_mount_apps(void); +void uwsgi_socket_nb(int); +void uwsgi_socket_b(int); +int uwsgi_write_nb(int, char *, size_t, int); +int uwsgi_read_nb(int, char *, size_t, int); +ssize_t uwsgi_read_true_nb(int, char *, size_t, int); +int uwsgi_read_whole_true_nb(int, char *, size_t, int); +int uwsgi_read_uh(int fd, struct uwsgi_header *, int); +int uwsgi_proxy_nb(struct wsgi_request *, char *, struct uwsgi_buffer *, size_t, int); + +int uwsgi_read_with_realloc(int, char **, size_t *, int, uint8_t *, uint8_t *); +int uwsgi_write_true_nb(int, char *, size_t, int); + +void uwsgi_destroy_request(struct wsgi_request *); + +void uwsgi_systemd_init(char *); + +void uwsgi_sig_pause(void); + +void uwsgi_ignition(void); + +int uwsgi_respawn_worker(int); + +socklen_t socket_to_in_addr(char *, char *, int, struct sockaddr_in *); +socklen_t socket_to_un_addr(char *, struct sockaddr_un *); +socklen_t socket_to_in_addr6(char *, char *, int, struct sockaddr_in6 *); + +int uwsgi_get_shared_socket_fd_by_num(int); +struct uwsgi_socket *uwsgi_get_shared_socket_by_num(int); + +struct uwsgi_socket *uwsgi_get_socket_by_num(int); + +int uwsgi_get_shared_socket_num(struct uwsgi_socket *); + +#ifdef __linux__ +void uwsgi_set_cgroup(void); +long uwsgi_num_from_file(char *, int); +#endif + +void uwsgi_add_sockets_to_queue(int, int); +void uwsgi_del_sockets_from_queue(int); + +int uwsgi_run_command_and_wait(char *, char *); +int uwsgi_run_command_putenv_and_wait(char *, char *, char **, unsigned int); +int uwsgi_call_symbol(char *); + +void uwsgi_manage_signal_cron(time_t); +pid_t uwsgi_run_command(char *, int *, int); + +void uwsgi_manage_command_cron(time_t); + +int *uwsgi_attach_fd(int, int *, char *, size_t); + +int uwsgi_count_sockets(struct uwsgi_socket *); +int uwsgi_file_exists(char *); + +int uwsgi_signal_registered(uint8_t); + +int uwsgi_endswith(char *, char *); + + +void uwsgi_chown(char *, char *); + +char *uwsgi_get_binary_path(char *); + +char *uwsgi_lower(char *, size_t); +int uwsgi_num2str2n(int, char *, int); +void create_logpipe(void); + +char *uwsgi_str_contains(char *, int, char); + +int uwsgi_simple_parse_vars(struct wsgi_request *, char *, char *); + +void uwsgi_build_mime_dict(char *); +struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **, char *, int, char *, int); +void uwsgi_dyn_dict_del(struct uwsgi_dyn_dict *); + + +void uwsgi_apply_config_pass(char symbol, char *(*)(char *)); + +void uwsgi_mule(int); + +char *uwsgi_string_get_list(struct uwsgi_string_list **, int, size_t *); + +void uwsgi_fixup_fds(int, int, struct uwsgi_gateway *); + +void uwsgi_set_processname(char *); + +void http_url_decode(char *, uint16_t *, char *); +void http_url_encode(char *, uint16_t *, char *); + +pid_t uwsgi_fork(char *); + +struct uwsgi_mule *get_mule_by_id(int); +struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **, struct uwsgi_mule *); + +int uwsgi_farm_has_mule(struct uwsgi_farm *, int); +struct uwsgi_farm *get_farm_by_name(char *); + + +struct uwsgi_subscribe_node { + + char name[0xff]; + uint16_t len; + uint8_t modifier1; + uint8_t modifier2; + + time_t last_check; + + // absolute number of requests + uint64_t requests; + // number of requests since last subscription ping + uint64_t last_requests; + + uint64_t tx; + uint64_t rx; + + int death_mark; + uint64_t reference; + uint64_t cores; + uint64_t load; + uint64_t failcnt; + + uint64_t weight; + uint64_t wrr; + + time_t unix_check; + + // used by unix credentials + pid_t pid; + uid_t uid; + gid_t gid; + + char notify[102]; + + struct uwsgi_subscribe_slot *slot; + + struct uwsgi_subscribe_node *next; +}; + +struct uwsgi_subscribe_slot { + + char key[0xff]; + uint16_t keylen; + + uint32_t hash; + + uint64_t hits; + + struct uwsgi_subscribe_node *nodes; + + struct uwsgi_subscribe_slot *prev; + struct uwsgi_subscribe_slot *next; + +#ifdef UWSGI_SSL + EVP_PKEY *sign_public_key; + EVP_MD_CTX *sign_ctx; + uint8_t sni_enabled; +#endif + +}; + +int mule_send_msg(int, char *, size_t); + +uint32_t djb33x_hash(char *, uint64_t); +void create_signal_pipe(int *); +void create_msg_pipe(int *, int); +struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t); +struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t); +struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t); +int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_node *); +struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_req *); + +ssize_t uwsgi_mule_get_msg(int, int, char *, size_t, int); + +int uwsgi_signal_wait(int); +struct uwsgi_app *uwsgi_add_app(int, uint8_t, char *, int, void *, void *); +int uwsgi_signal_send(int, uint8_t); +int uwsgi_remote_signal_send(char *, uint8_t); + +void uwsgi_configure(); + +int uwsgi_read_response(int, struct uwsgi_header *, int, char **); +char *uwsgi_simple_file_read(char *); + +void uwsgi_send_subscription(char *, char *, size_t, uint8_t, uint8_t, uint8_t, char *, char *, char *, char *, char *); +void uwsgi_send_subscription_from_fd(int, char *, char *, size_t, uint8_t, uint8_t, uint8_t, char *, char *, char *, char *, char *); + +void uwsgi_subscribe(char *, uint8_t); +void uwsgi_subscribe2(char *, uint8_t); + +int uwsgi_is_bad_connection(int); +int uwsgi_long2str2n(unsigned long long, char *, int); + +#ifdef __linux__ +void uwsgi_build_unshare(char *, int *); +#ifdef MADV_MERGEABLE +void uwsgi_linux_ksm_map(void); +#endif +#endif + +#ifdef UWSGI_CAP +int uwsgi_build_cap(char *, cap_value_t **); +void uwsgi_apply_cap(cap_value_t *, int); +#endif + +void uwsgi_register_logger(char *, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)); +void uwsgi_append_logger(struct uwsgi_logger *); +void uwsgi_append_req_logger(struct uwsgi_logger *); +struct uwsgi_logger *uwsgi_get_logger(char *); +struct uwsgi_logger *uwsgi_get_logger_from_id(char *); + +char *uwsgi_getsockname(int); +char *uwsgi_get_var(struct wsgi_request *, char *, uint16_t, uint16_t *); + +struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *, char *); +struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int, char *); + +void escape_shell_arg(char *, size_t, char *); +void escape_json(char *, size_t, char *); + +void *uwsgi_malloc_shared(size_t); +void *uwsgi_calloc_shared(size_t); + +struct uwsgi_spooler *uwsgi_new_spooler(char *); + +struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *, size_t); + +int uwsgi_zerg_attach(char *); + +int uwsgi_manage_opt(char *, char *); + +void uwsgi_opt_print(char *, char *, void *); +void uwsgi_opt_true(char *, char *, void *); +void uwsgi_opt_false(char *, char *, void *); +void uwsgi_opt_set_str(char *, char *, void *); +void uwsgi_opt_custom(char *, char *, void *); +void uwsgi_opt_set_null(char *, char *, void *); +void uwsgi_opt_set_logger(char *, char *, void *); +void uwsgi_opt_set_req_logger(char *, char *, void *); +void uwsgi_opt_set_str_spaced(char *, char *, void *); +void uwsgi_opt_add_string_list(char *, char *, void *); +void uwsgi_opt_add_addr_list(char *, char *, void *); +void uwsgi_opt_add_string_list_custom(char *, char *, void *); +void uwsgi_opt_add_dyn_dict(char *, char *, void *); +void uwsgi_opt_binary_append_data(char *, char *, void *); +#ifdef UWSGI_PCRE +void uwsgi_opt_pcre_jit(char *, char *, void *); +void uwsgi_opt_add_regexp_dyn_dict(char *, char *, void *); +void uwsgi_opt_add_regexp_list(char *, char *, void *); +void uwsgi_opt_add_regexp_custom_list(char *, char *, void *); +#endif +void uwsgi_opt_set_int(char *, char *, void *); +void uwsgi_opt_uid(char *, char *, void *); +void uwsgi_opt_gid(char *, char *, void *); +void uwsgi_opt_set_rawint(char *, char *, void *); +void uwsgi_opt_set_16bit(char *, char *, void *); +void uwsgi_opt_set_64bit(char *, char *, void *); +void uwsgi_opt_set_megabytes(char *, char *, void *); +void uwsgi_opt_set_dyn(char *, char *, void *); +void uwsgi_opt_set_placeholder(char *, char *, void *); +void uwsgi_opt_add_shared_socket(char *, char *, void *); +void uwsgi_opt_add_socket(char *, char *, void *); +#ifdef UWSGI_SSL +void uwsgi_opt_add_ssl_socket(char *, char *, void *); +#endif +void uwsgi_opt_add_socket_no_defer(char *, char *, void *); +void uwsgi_opt_add_lazy_socket(char *, char *, void *); +void uwsgi_opt_add_cron(char *, char *, void *); +void uwsgi_opt_add_cron2(char *, char *, void *); +void uwsgi_opt_add_unique_cron(char *, char *, void *); +void uwsgi_opt_load_plugin(char *, char *, void *); +void uwsgi_opt_load_dl(char *, char *, void *); +void uwsgi_opt_load(char *, char *, void *); +void uwsgi_opt_safe_fd(char *, char *, void *); +#ifdef UWSGI_SSL +void uwsgi_opt_add_legion_cron(char *, char *, void *); +void uwsgi_opt_add_unique_legion_cron(char *, char *, void *); +void uwsgi_opt_sni(char *, char *, void *); +struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *, char *, char *, char *, char *); +void uwsgi_ssl_del_sni_item(char *, uint16_t); +char *uwsgi_write_pem_to_file(char *, char *, size_t, char *); +#endif +void uwsgi_opt_flock(char *, char *, void *); +void uwsgi_opt_flock_wait(char *, char *, void *); +void uwsgi_opt_load_ini(char *, char *, void *); +#ifdef UWSGI_XML +void uwsgi_opt_load_xml(char *, char *, void *); +#endif +#ifdef UWSGI_YAML +void uwsgi_opt_load_yml(char *, char *, void *); +#endif +#ifdef UWSGI_JSON +void uwsgi_opt_load_json(char *, char *, void *); +#endif + +void uwsgi_opt_set_umask(char *, char *, void *); +void uwsgi_opt_add_spooler(char *, char *, void *); +void uwsgi_opt_add_daemon(char *, char *, void *); +void uwsgi_opt_add_daemon2(char *, char *, void *); +void uwsgi_opt_set_uid(char *, char *, void *); +void uwsgi_opt_set_gid(char *, char *, void *); +void uwsgi_opt_set_immediate_uid(char *, char *, void *); +void uwsgi_opt_set_immediate_gid(char *, char *, void *); +void uwsgi_opt_set_env(char *, char *, void *); +void uwsgi_opt_unset_env(char *, char *, void *); +void uwsgi_opt_pidfile_signal(char *, char *, void *); + +void uwsgi_opt_check_static(char *, char *, void *); +void uwsgi_opt_fileserve_mode(char *, char *, void *); +void uwsgi_opt_static_map(char *, char *, void *); + +void uwsgi_opt_add_mule(char *, char *, void *); +void uwsgi_opt_add_mules(char *, char *, void *); +void uwsgi_opt_add_farm(char *, char *, void *); + +void uwsgi_opt_signal(char *, char *, void *); + +void uwsgi_opt_snmp(char *, char *, void *); +void uwsgi_opt_snmp_community(char *, char *, void *); + +void uwsgi_opt_logfile_chmod(char *, char *, void *); + +void uwsgi_opt_log_date(char *, char *, void *); +void uwsgi_opt_chmod_socket(char *, char *, void *); + +void uwsgi_opt_max_vars(char *, char *, void *); +void uwsgi_opt_deprecated(char *, char *, void *); + +void uwsgi_opt_noop(char *, char *, void *); + +void uwsgi_opt_logic(char *, char *, void *); +int uwsgi_logic_opt_for(char *, char *); +int uwsgi_logic_opt_for_glob(char *, char *); +int uwsgi_logic_opt_for_times(char *, char *); +int uwsgi_logic_opt_for_readline(char *, char *); +int uwsgi_logic_opt_if_env(char *, char *); +int uwsgi_logic_opt_if_not_env(char *, char *); +int uwsgi_logic_opt_if_opt(char *, char *); +int uwsgi_logic_opt_if_not_opt(char *, char *); +int uwsgi_logic_opt_if_exists(char *, char *); +int uwsgi_logic_opt_if_not_exists(char *, char *); +int uwsgi_logic_opt_if_file(char *, char *); +int uwsgi_logic_opt_if_not_file(char *, char *); +int uwsgi_logic_opt_if_dir(char *, char *); +int uwsgi_logic_opt_if_not_dir(char *, char *); +int uwsgi_logic_opt_if_reload(char *, char *); +int uwsgi_logic_opt_if_not_reload(char *, char *); +int uwsgi_logic_opt_if_plugin(char *, char *); +int uwsgi_logic_opt_if_not_plugin(char *, char *); +int uwsgi_logic_opt_if_hostname(char *, char *); +int uwsgi_logic_opt_if_not_hostname(char *, char *); +int uwsgi_logic_opt_if_hostname_match(char *, char *); +int uwsgi_logic_opt_if_not_hostname_match(char *, char *); + + +void uwsgi_opt_resolve(char *, char *, void *); + +#ifdef UWSGI_CAP +void uwsgi_opt_set_cap(char *, char *, void *); +void uwsgi_opt_set_emperor_cap(char *, char *, void *); +#endif +#ifdef __linux__ +void uwsgi_opt_set_unshare(char *, char *, void *); +#endif + +int uwsgi_tmpfd(); +FILE *uwsgi_tmpfile(); + +#ifdef UWSGI_ROUTING +struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, char *)); +void uwsgi_opt_add_route(char *, char *, void *); +int uwsgi_apply_routes(struct wsgi_request *); +void uwsgi_apply_final_routes(struct wsgi_request *); +int uwsgi_apply_error_routes(struct wsgi_request *); +int uwsgi_apply_response_routes(struct wsgi_request *); +int uwsgi_apply_routes_do(struct uwsgi_route *, struct wsgi_request *, char *, uint16_t); +void uwsgi_register_embedded_routers(void); +void uwsgi_routing_dump(); +struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *, struct uwsgi_route *, char *, uint16_t, char *, size_t); +int uwsgi_route_api_func(struct wsgi_request *, char *, char *); +struct uwsgi_route_condition *uwsgi_register_route_condition(char *, int (*) (struct wsgi_request *, struct uwsgi_route *)); +void uwsgi_fixup_routes(struct uwsgi_route *); +#endif + +void uwsgi_reload(char **); + +char *uwsgi_chomp(char *); +char *uwsgi_chomp2(char *); +int uwsgi_file_to_string_list(char *, struct uwsgi_string_list **); +void uwsgi_backtrace(int); +void uwsgi_check_logrotate(void); +char *uwsgi_check_touches(struct uwsgi_string_list *); + +void uwsgi_manage_zerg(int, int, int *); + +time_t uwsgi_now(void); + +int uwsgi_calc_cheaper(void); +int uwsgi_cheaper_algo_spare(int); +int uwsgi_cheaper_algo_backlog(int); +int uwsgi_cheaper_algo_backlog2(int); +int uwsgi_cheaper_algo_manual(int); + +int uwsgi_master_log(void); +int uwsgi_master_req_log(void); +void uwsgi_flush_logs(void); + +void uwsgi_register_cheaper_algo(char *, int (*)(int)); + +void uwsgi_setup_locking(void); +int uwsgi_fcntl_lock(int); +int uwsgi_fcntl_is_locked(int); + +void uwsgi_emulate_cow_for_apps(int); + +char *uwsgi_read_fd(int, size_t *, int); + +void uwsgi_setup_post_buffering(void); + +struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *); + +void uwsgi_write_pidfile(char *); +void uwsgi_write_pidfile_explicit(char *, pid_t); +int uwsgi_write_intfile(char *, int); + +void uwsgi_protected_close(int); +ssize_t uwsgi_protected_read(int, void *, size_t); +int uwsgi_socket_uniq(struct uwsgi_socket *, struct uwsgi_socket *); +int uwsgi_socket_is_already_bound(char *name); + +char *uwsgi_expand_path(char *, int, char *); +int uwsgi_try_autoload(char *); + +uint64_t uwsgi_micros(void); +uint64_t uwsgi_millis(void); +int uwsgi_is_file(char *); +int uwsgi_is_file2(char *, struct stat *); +int uwsgi_is_dir(char *); +int uwsgi_is_link(char *); + +void uwsgi_receive_signal(int, char *, int); +void uwsgi_exec_atexit(void); + +struct uwsgi_stats { + char *base; + off_t pos; + size_t tabs; + size_t chunk; + size_t size; + int minified; + int dirty; +}; + +struct uwsgi_stats_pusher_instance; + +struct uwsgi_stats_pusher { + char *name; + void (*func) (struct uwsgi_stats_pusher_instance *, time_t, char *, size_t); + int raw; + struct uwsgi_stats_pusher *next; +}; + +struct uwsgi_stats_pusher_instance { + struct uwsgi_stats_pusher *pusher; + char *arg; + void *data; + int raw; + int configured; + int freq; + time_t last_run; + // retries + int needs_retry; + int retries; + int max_retries; + int retry_delay; + time_t next_retry; + + struct uwsgi_stats_pusher_instance *next; +}; + +struct uwsgi_thread; +void uwsgi_stats_pusher_loop(struct uwsgi_thread *); + +void uwsgi_stats_pusher_setup(void); +void uwsgi_send_stats(int, struct uwsgi_stats *(*func) (void)); +struct uwsgi_stats *uwsgi_master_generate_stats(void); +struct uwsgi_stats_pusher * uwsgi_register_stats_pusher(char *, void (*)(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t)); + +struct uwsgi_stats *uwsgi_stats_new(size_t); +int uwsgi_stats_symbol(struct uwsgi_stats *, char); +int uwsgi_stats_comma(struct uwsgi_stats *); +int uwsgi_stats_object_open(struct uwsgi_stats *); +int uwsgi_stats_object_close(struct uwsgi_stats *); +int uwsgi_stats_list_open(struct uwsgi_stats *); +int uwsgi_stats_list_close(struct uwsgi_stats *); +int uwsgi_stats_keyval(struct uwsgi_stats *, char *, char *); +int uwsgi_stats_keyval_comma(struct uwsgi_stats *, char *, char *); +int uwsgi_stats_keyvalnum(struct uwsgi_stats *, char *, char *, unsigned long long); +int uwsgi_stats_keyvalnum_comma(struct uwsgi_stats *, char *, char *, unsigned long long); +int uwsgi_stats_keyvaln(struct uwsgi_stats *, char *, char *, int); +int uwsgi_stats_keyvaln_comma(struct uwsgi_stats *, char *, char *, int); +int uwsgi_stats_key(struct uwsgi_stats *, char *); +int uwsgi_stats_keylong(struct uwsgi_stats *, char *, unsigned long long); +int uwsgi_stats_keylong_comma(struct uwsgi_stats *, char *, unsigned long long); +int uwsgi_stats_keyslong(struct uwsgi_stats *, char *, long long); +int uwsgi_stats_keyslong_comma(struct uwsgi_stats *, char *, long long); +int uwsgi_stats_str(struct uwsgi_stats *, char *); + +char *uwsgi_substitute(char *, char *, char *); + +void uwsgi_opt_add_custom_option(char *, char *, void *); +void uwsgi_opt_cflags(char *, char *, void *); +void uwsgi_opt_build_plugin(char *, char *, void *); +void uwsgi_opt_dot_h(char *, char *, void *); +void uwsgi_opt_config_py(char *, char *, void *); +void uwsgi_opt_connect_and_read(char *, char *, void *); +void uwsgi_opt_extract(char *, char *, void *); + +char *uwsgi_get_dot_h(); +char *uwsgi_get_config_py(); +char *uwsgi_get_cflags(); + +struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t); + +void trigger_harakiri(int); + +void uwsgi_setup_systemd(); +void uwsgi_setup_upstart(); +void uwsgi_setup_zerg(); +void uwsgi_setup_inherited_sockets(); +void uwsgi_setup_emperor(); + +#ifdef UWSGI_SSL +void uwsgi_ssl_init(void); +SSL_CTX *uwsgi_ssl_new_server_context(char *, char *, char *, char *, char *); +char *uwsgi_rsa_sign(char *, char *, size_t, unsigned int *); +char *uwsgi_sanitize_cert_filename(char *, char *, uint16_t); +void uwsgi_opt_scd(char *, char *, void *); +int uwsgi_subscription_sign_check(struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_req *); + +char *uwsgi_sha1(char *, size_t, char *); +char *uwsgi_sha1_2n(char *, size_t, char *, size_t, char *); +char *uwsgi_md5(char *, size_t, char *); +#endif + +void uwsgi_opt_ssa(char *, char *, void *); + +int uwsgi_no_subscriptions(struct uwsgi_subscribe_slot **); +void uwsgi_deadlock_check(pid_t); + + +struct uwsgi_logchunk { + char *name; + char *ptr; + size_t len; + int vec; + long pos; + long pos_len; + int type; + int free; + ssize_t(*func) (struct wsgi_request *, char **); + struct uwsgi_logchunk *next; +}; + +void uwsgi_build_log_format(char *); + +void uwsgi_add_logchunk(int, int, char *, size_t); +struct uwsgi_logchunk *uwsgi_register_logchunk(char *, ssize_t (*)(struct wsgi_request *, char **), int); + +void uwsgi_logit_simple(struct wsgi_request *); +void uwsgi_logit_lf(struct wsgi_request *); +void uwsgi_logit_lf_strftime(struct wsgi_request *); + +struct uwsgi_logvar *uwsgi_logvar_get(struct wsgi_request *, char *, uint8_t); +void uwsgi_logvar_add(struct wsgi_request *, char *, uint8_t, char *, uint8_t); + +// scanners are instances of 'imperial_monitor' +struct uwsgi_emperor_scanner { + char *arg; + int fd; + void *data; + void (*event_func) (struct uwsgi_emperor_scanner *); + struct uwsgi_imperial_monitor *monitor; + struct uwsgi_emperor_scanner *next; +}; + +void uwsgi_register_imperial_monitor(char *, void (*)(struct uwsgi_emperor_scanner *), void (*)(struct uwsgi_emperor_scanner *)); +int uwsgi_emperor_is_valid(char *); + +// an instance (called vassal) is a uWSGI stack running +// it is identified by the name of its config file +// a vassal is 'loyal' as soon as it manages a request +struct uwsgi_instance { + struct uwsgi_instance *ui_prev; + struct uwsgi_instance *ui_next; + + char name[0xff]; + pid_t pid; + + int status; + time_t born; + time_t last_mod; + time_t last_loyal; + time_t last_accepting; + time_t last_ready; + + time_t last_run; + time_t first_run; + + time_t last_heartbeat; + + uint64_t respawns; + int use_config; + + int pipe[2]; + int pipe_config[2]; + + char *config; + uint32_t config_len; + + int loyal; + + int zerg; + + int ready; + int accepting; + + struct uwsgi_emperor_scanner *scanner; + + uid_t uid; + gid_t gid; + + int on_demand_fd; + char *socket_name; + time_t cursed_at; +}; + +struct uwsgi_instance *emperor_get_by_fd(int); +struct uwsgi_instance *emperor_get(char *); +void emperor_stop(struct uwsgi_instance *); +void emperor_curse(struct uwsgi_instance *); +void emperor_respawn(struct uwsgi_instance *, time_t); +void emperor_add(struct uwsgi_emperor_scanner *, char *, time_t, char *, uint32_t, uid_t, gid_t, char *); +void emperor_back_to_ondemand(struct uwsgi_instance *); + +void uwsgi_exec_command_with_args(char *); + +void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *); +void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *); +void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *); +void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *); + +void uwsgi_register_clock(struct uwsgi_clock *); +void uwsgi_set_clock(char *name); + +void uwsgi_init_default(void); +void uwsgi_setup_reload(void); +void uwsgi_autoload_plugins_by_name(char *); +void uwsgi_commandline_config(void); + +void uwsgi_setup_log(void); +void uwsgi_setup_log_master(void); + +void uwsgi_setup_shared_sockets(void); + +void uwsgi_setup_mules_and_farms(void); + +void uwsgi_setup_workers(void); +void uwsgi_map_sockets(void); + +void uwsgi_set_cpu_affinity(void); + +void uwsgi_emperor_start(void); + +void uwsgi_bind_sockets(void); +void uwsgi_set_sockets_protocols(void); + +struct uwsgi_buffer *uwsgi_buffer_new(size_t); +int uwsgi_buffer_append(struct uwsgi_buffer *, char *, size_t); +int uwsgi_buffer_fix(struct uwsgi_buffer *, size_t); +int uwsgi_buffer_ensure(struct uwsgi_buffer *, size_t); +void uwsgi_buffer_destroy(struct uwsgi_buffer *); +int uwsgi_buffer_u8(struct uwsgi_buffer *, uint8_t); +int uwsgi_buffer_byte(struct uwsgi_buffer *, char); +int uwsgi_buffer_u16le(struct uwsgi_buffer *, uint16_t); +int uwsgi_buffer_u16be(struct uwsgi_buffer *, uint16_t); +int uwsgi_buffer_u32be(struct uwsgi_buffer *, uint32_t); +int uwsgi_buffer_u32le(struct uwsgi_buffer *, uint32_t); +int uwsgi_buffer_u64le(struct uwsgi_buffer *, uint64_t); +int uwsgi_buffer_f32be(struct uwsgi_buffer *, float); +int uwsgi_buffer_u24be(struct uwsgi_buffer *, uint32_t); +int uwsgi_buffer_u64be(struct uwsgi_buffer *, uint64_t); +int uwsgi_buffer_f64be(struct uwsgi_buffer *, double); +int uwsgi_buffer_num64(struct uwsgi_buffer *, int64_t); +int uwsgi_buffer_append_keyval(struct uwsgi_buffer *, char *, uint16_t, char *, uint16_t); +int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *, char *, uint32_t, char *, uint32_t); +int uwsgi_buffer_append_keynum(struct uwsgi_buffer *, char *, uint16_t, int64_t); +int uwsgi_buffer_append_valnum(struct uwsgi_buffer *, int64_t); +int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *, void *); +int uwsgi_buffer_append_keyipv4(struct uwsgi_buffer *, char *, uint16_t, void *); +int uwsgi_buffer_decapitate(struct uwsgi_buffer *, size_t); +int uwsgi_buffer_append_base64(struct uwsgi_buffer *, char *, size_t); +int uwsgi_buffer_insert(struct uwsgi_buffer *, size_t, char *, size_t); +int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *, size_t, size_t); +int uwsgi_buffer_append_chunked(struct uwsgi_buffer *, size_t); +int uwsgi_buffer_append_json(struct uwsgi_buffer *, char *, size_t); +int uwsgi_buffer_set_uh(struct uwsgi_buffer *, uint8_t, uint8_t); +void uwsgi_buffer_map(struct uwsgi_buffer *, char *, size_t); +struct uwsgi_buffer *uwsgi_buffer_from_file(char *); + +ssize_t uwsgi_buffer_write_simple(struct wsgi_request *, struct uwsgi_buffer *); + +struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *, char *, uint16_t, char *, uint16_t); +struct uwsgi_buffer *uwsgi_to_http_dumb(struct wsgi_request *, char *, uint16_t, char *, uint16_t); + +ssize_t uwsgi_pipe(int, int, int); +ssize_t uwsgi_pipe_sized(int, int, size_t, int); + +int uwsgi_buffer_send(struct uwsgi_buffer *, int); +void uwsgi_master_cleanup_hooks(void); + +pid_t uwsgi_daemonize2(); + +void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *, char *, char *, time_t, uid_t, gid_t, char *); + +#if defined(__linux__) +#define UWSGI_ELF +char *uwsgi_elf_section(char *, char *, size_t *); +#endif + +void uwsgi_alarm_log_check(char *, size_t); +void uwsgi_alarm_run(struct uwsgi_alarm_instance *, char *, size_t); +void uwsgi_register_alarm(char *, void (*)(struct uwsgi_alarm_instance *), void (*)(struct uwsgi_alarm_instance *, char *, size_t)); +void uwsgi_register_embedded_alarms(); +void uwsgi_alarms_init(); +void uwsgi_alarm_trigger(char *, char *, size_t); + +struct uwsgi_thread { + pthread_t tid; + pthread_attr_t tattr; + int pipe[2]; + int queue; + ssize_t rlen; + void *data; + char *buf; + off_t pos; + size_t len; + uint64_t custom0; + uint64_t custom1; + uint64_t custom2; + uint64_t custom3; + // linked list for offloaded requests + struct uwsgi_offload_request *offload_requests_head; + struct uwsgi_offload_request *offload_requests_tail; + void (*func) (struct uwsgi_thread *); +}; +struct uwsgi_thread *uwsgi_thread_new(void (*)(struct uwsgi_thread *)); +struct uwsgi_thread *uwsgi_thread_new_with_data(void (*)(struct uwsgi_thread *), void *data); + +struct uwsgi_offload_request { + // the request socket + int s; + // the peer + int fd; + int fd2; + + // if set the current request is expected to end leaving + // the offload thread do its job + uint8_t takeover; + + // internal state + int status; + + // a filename, a socket... + char *name; + + off_t pos; + char *buf; + off_t buf_pos; + + size_t to_write; + size_t len; + size_t written; + + // a uwsgi_buffer (will be destroyed at the end of the task) + struct uwsgi_buffer *ubuf; + + struct uwsgi_offload_engine *engine; + + // this pipe is used for notifications + int pipe[2]; + + struct uwsgi_offload_request *prev; + struct uwsgi_offload_request *next; + + // added in 2.1 + struct uwsgi_buffer *ubuf1; + struct uwsgi_buffer *ubuf2; + struct uwsgi_buffer *ubuf3; + struct uwsgi_buffer *ubuf4; + struct uwsgi_buffer *ubuf5; + struct uwsgi_buffer *ubuf6; + struct uwsgi_buffer *ubuf7; + struct uwsgi_buffer *ubuf8; + + int64_t custom1; + int64_t custom2; + int64_t custom3; + int64_t custom4; + int64_t custom5; + int64_t custom6; + int64_t custom7; + int64_t custom8; + + void *data; + void (*free)(struct uwsgi_offload_request *); +}; + +struct uwsgi_offload_engine { + char *name; + int (*prepare_func)(struct wsgi_request *, struct uwsgi_offload_request *); + int (*event_func) (struct uwsgi_thread *, struct uwsgi_offload_request *, int); + struct uwsgi_offload_engine *next; +}; + +struct uwsgi_offload_engine *uwsgi_offload_engine_by_name(char *); +struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *, int (*)(struct wsgi_request *, struct uwsgi_offload_request *), int (*) (struct uwsgi_thread *, struct uwsgi_offload_request *, int)); + +void uwsgi_offload_setup(struct uwsgi_offload_engine *, struct uwsgi_offload_request *, struct wsgi_request *, uint8_t); +int uwsgi_offload_run(struct wsgi_request *, struct uwsgi_offload_request *, int *); +void uwsgi_offload_engines_register_all(void); + +struct uwsgi_thread *uwsgi_offload_thread_start(void); +int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t); +int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *); +int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t); +int uwsgi_offload_request_pipe_do(struct wsgi_request *, int, size_t); + +int uwsgi_simple_sendfile(struct wsgi_request *, int, size_t, size_t); +int uwsgi_simple_write(struct wsgi_request *, char *, size_t); + + +void uwsgi_subscription_set_algo(char *); +struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht(void); + +int uwsgi_check_pidfile(char *); +void uwsgi_daemons_spawn_all(); + +int uwsgi_daemon_check_pid_death(pid_t); +int uwsgi_daemon_check_pid_reload(pid_t); +void uwsgi_daemons_smart_check(); + +void uwsgi_setup_thread_req(long, struct wsgi_request *); +void uwsgi_loop_cores_run(void *(*)(void *)); + +int uwsgi_kvlist_parse(char *, size_t, char, int, ...); +int uwsgi_send_http_stats(int); + +ssize_t uwsgi_simple_request_read(struct wsgi_request *, char *, size_t); +int uwsgi_plugin_modifier1(char *); + +void *cache_udp_server_loop(void *); + +int uwsgi_user_lock(int); +int uwsgi_user_unlock(int); + +void simple_loop_run_int(int); + +char *uwsgi_strip(char *); + +#ifdef UWSGI_SSL +void uwsgi_opt_legion(char *, char *, void *); +void uwsgi_opt_legion_mcast(char *, char *, void *); +struct uwsgi_legion *uwsgi_legion_register(char *, char *, char *, char *, char *); +void uwsgi_opt_legion_node(char *, char *, void *); +void uwsgi_legion_register_node(struct uwsgi_legion *, char *); +void uwsgi_opt_legion_quorum(char *, char *, void *); +void uwsgi_opt_legion_hook(char *, char *, void *); +void uwsgi_legion_register_hook(struct uwsgi_legion *, char *, char *); +void uwsgi_opt_legion_scroll(char *, char *, void *); +void uwsgi_legion_add(struct uwsgi_legion *); +void uwsgi_legion_announce_death(void); +char *uwsgi_ssl_rand(size_t); +void uwsgi_start_legions(void); +int uwsgi_legion_announce(struct uwsgi_legion *); +struct uwsgi_legion *uwsgi_legion_get_by_name(char *); +struct uwsgi_legion_action *uwsgi_legion_action_get(char *); +struct uwsgi_legion_action *uwsgi_legion_action_register(char *, int (*)(struct uwsgi_legion *, char *)); +int uwsgi_legion_action_call(char *, struct uwsgi_legion *, struct uwsgi_string_list *); +void uwsgi_legion_atexit(void); +#endif + +struct uwsgi_option *uwsgi_opt_get(char *); +int uwsgi_opt_exists(char *); +int uwsgi_valid_fd(int); +void uwsgi_close_all_fds(void); + +int check_hex(char *, int); +void uwsgi_uuid(char *); +int uwsgi_uuid_cmp(char *, char *); + +int uwsgi_legion_i_am_the_lord(char *); +char *uwsgi_legion_lord_scroll(char *, uint16_t *); +void uwsgi_additional_header_add(struct wsgi_request *, char *, uint16_t); +void uwsgi_remove_header(struct wsgi_request *, char *, uint16_t); + +void uwsgi_proto_hooks_setup(void); + +char *uwsgi_base64_decode(char *, size_t, size_t *); +char *uwsgi_base64_encode(char *, size_t, size_t *); + +void uwsgi_subscribe_all(uint8_t, int); +#define uwsgi_unsubscribe_all() uwsgi_subscribe_all(1, 1) + +void uwsgi_websockets_init(void); +int uwsgi_websocket_send(struct wsgi_request *, char *, size_t); +int uwsgi_websocket_send_binary(struct wsgi_request *, char *, size_t); +struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *); +struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *); + +char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int); + +uint16_t uwsgi_be16(char *); +uint32_t uwsgi_be32(char *); +uint64_t uwsgi_be64(char *); + +int uwsgi_websocket_handshake(struct wsgi_request *, char *, uint16_t, char *, uint16_t, char *, uint16_t); + +int uwsgi_response_prepare_headers(struct wsgi_request *, char *, uint16_t); +int uwsgi_response_prepare_headers_int(struct wsgi_request *, int); +int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t); +int uwsgi_response_add_header_force(struct wsgi_request *, char *, uint16_t, char *, uint16_t); +int uwsgi_response_commit_headers(struct wsgi_request *); +int uwsgi_response_sendfile_do(struct wsgi_request *, int, size_t, size_t); +int uwsgi_response_sendfile_do_can_close(struct wsgi_request *, int, size_t, size_t, int); + +struct uwsgi_buffer *uwsgi_proto_base_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t); + +int uwsgi_simple_wait_write_hook(int, int); +int uwsgi_simple_wait_read_hook(int, int); +int uwsgi_simple_wait_read2_hook(int, int, int, int *); +int uwsgi_simple_wait_milliseconds_hook(int); +int uwsgi_response_write_headers_do(struct wsgi_request *); +char *uwsgi_request_body_read(struct wsgi_request *, ssize_t , ssize_t *); +char *uwsgi_request_body_readline(struct wsgi_request *, ssize_t, ssize_t *); +void uwsgi_request_body_seek(struct wsgi_request *, off_t); + +struct uwsgi_buffer *uwsgi_proto_base_prepare_headers(struct wsgi_request *, char *, uint16_t); +struct uwsgi_buffer *uwsgi_proto_base_cgi_prepare_headers(struct wsgi_request *, char *, uint16_t); +int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t); +int uwsgi_response_writev_body_do(struct wsgi_request *, struct iovec *, size_t); + +int uwsgi_proto_base_sendfile(struct wsgi_request *, int, size_t, size_t); +#ifdef UWSGI_SSL +int uwsgi_proto_ssl_sendfile(struct wsgi_request *, int, size_t, size_t); +#endif + +ssize_t uwsgi_sendfile_do(int, int, size_t, size_t); +int uwsgi_proto_base_fix_headers(struct wsgi_request *); +int uwsgi_response_add_content_length(struct wsgi_request *, uint64_t); +void uwsgi_fix_range_for_size(enum uwsgi_range*, int64_t*, int64_t*, int64_t); +void uwsgi_request_fix_range_for_size(struct wsgi_request *, int64_t); +int uwsgi_response_add_content_range(struct wsgi_request *, int64_t, int64_t, int64_t); +int uwsgi_response_add_expires(struct wsgi_request *, uint64_t); +int uwsgi_response_add_last_modified(struct wsgi_request *, uint64_t); +int uwsgi_response_add_date(struct wsgi_request *, char *, uint16_t, uint64_t); + +const char *uwsgi_http_status_msg(char *, uint16_t *); +int uwsgi_stats_dump_vars(struct uwsgi_stats *, struct uwsgi_core *); +int uwsgi_stats_dump_request(struct uwsgi_stats *, struct uwsgi_core *); + +int uwsgi_contains_n(char *, size_t, char *, size_t); + +char *uwsgi_upload_progress_create(struct wsgi_request *, int *); +int uwsgi_upload_progress_update(struct wsgi_request *, int, size_t); +void uwsgi_upload_progress_destroy(char *, int); + +void uwsgi_time_bomb(int, int); +void uwsgi_master_manage_emperor(void); +void uwsgi_master_manage_udp(int); + +void uwsgi_threaded_logger_spawn(void); + +void uwsgi_master_check_idle(void); +int uwsgi_master_check_workers_deadline(void); +int uwsgi_master_check_gateways_deadline(void); +int uwsgi_master_check_mules_deadline(void); +int uwsgi_master_check_spoolers_deadline(void); +int uwsgi_master_check_crons_deadline(void); +int uwsgi_master_check_spoolers_death(int); +int uwsgi_master_check_emperor_death(int); +int uwsgi_master_check_mules_death(int); +int uwsgi_master_check_gateways_death(int); +int uwsgi_master_check_daemons_death(int); + +void uwsgi_master_check_death(void); +int uwsgi_master_check_reload(char **); +void uwsgi_master_commit_status(void); +void uwsgi_master_check_chain(void); + +void uwsgi_master_fix_request_counters(void); +int uwsgi_master_manage_events(int); + +void uwsgi_block_signal(int); +void uwsgi_unblock_signal(int); + +int uwsgi_worker_is_busy(int); + +void uwsgi_post_accept(struct wsgi_request *); +void uwsgi_tcp_nodelay(int); + +struct uwsgi_exception_handler_instance; +struct uwsgi_exception_handler { + char *name; + int (*func)(struct uwsgi_exception_handler_instance *, char *, size_t); + struct uwsgi_exception_handler *next; +}; + +struct uwsgi_exception_handler_instance { + struct uwsgi_exception_handler *handler; + int configured; + char *arg; + uint32_t custom32; + uint64_t custom64; + void *custom_ptr; +}; + +void uwsgi_exception_setup_handlers(void); +struct uwsgi_exception_handler *uwsgi_exception_handler_by_name(char *); + +void uwsgi_manage_exception(struct wsgi_request *, int); +int uwsgi_exceptions_catch(struct wsgi_request *); +uint64_t uwsgi_worker_exceptions(int); +struct uwsgi_exception_handler *uwsgi_register_exception_handler(char *, int (*)(struct uwsgi_exception_handler_instance *, char *, size_t)); + +char *proxy1_parse(char *ptr, char *watermark, char **src, uint16_t *src_len, char **dst, uint16_t *dst_len, char **src_port, uint16_t *src_port_len, char **dst_port, uint16_t *dst_port_len); +void uwsgi_async_queue_is_full(time_t); +char *uwsgi_get_header(struct wsgi_request *, char *, uint16_t, uint16_t *); + +void uwsgi_alarm_thread_start(void); +void uwsgi_exceptions_handler_thread_start(void); + +#define uwsgi_response_add_connection_close(x) uwsgi_response_add_header(x, (char *)"Connection", 10, (char *)"close", 5) +#define uwsgi_response_add_content_type(x, y, z) uwsgi_response_add_header(x, (char *)"Content-Type", 12, y, z) + +struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *, char *); + +int plugin_already_loaded(const char *); +struct uwsgi_plugin *uwsgi_plugin_get(const char *); + +struct uwsgi_cache_magic_context { + char *cmd; + uint16_t cmd_len; + char *key; + uint16_t key_len; + uint64_t size; + uint64_t expires; + char *status; + uint16_t status_len; + char *cache; + uint16_t cache_len; +}; + +char *uwsgi_cache_magic_get(char *, uint16_t, uint64_t *, uint64_t *, char *); +int uwsgi_cache_magic_set(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t, char *); +int uwsgi_cache_magic_del(char *, uint16_t, char *); +int uwsgi_cache_magic_exists(char *, uint16_t, char *); +int uwsgi_cache_magic_clear(char *); +void uwsgi_cache_magic_context_hook(char *, uint16_t, char *, uint16_t, void *); + +char *uwsgi_legion_scrolls(char *, uint64_t *); +int uwsgi_emperor_vassal_start(struct uwsgi_instance *); + +#ifdef UWSGI_ZLIB +#include +int uwsgi_deflate_init(z_stream *, char *, size_t); +int uwsgi_inflate_init(z_stream *, char *, size_t); +char *uwsgi_deflate(z_stream *, char *, size_t, size_t *); +void uwsgi_crc32(uint32_t *, char *, size_t); +struct uwsgi_buffer *uwsgi_gzip(char *, size_t); +struct uwsgi_buffer *uwsgi_zlib_decompress(char *, size_t); +int uwsgi_gzip_fix(z_stream *, uint32_t, struct uwsgi_buffer *, size_t); +char *uwsgi_gzip_chunk(z_stream *, uint32_t *, char *, size_t, size_t *); +int uwsgi_gzip_prepare(z_stream *, char *, size_t, uint32_t *); +#endif + +char *uwsgi_get_cookie(struct wsgi_request *, char *, uint16_t, uint16_t *); +char *uwsgi_get_qs(struct wsgi_request *, char *, uint16_t, uint16_t *); + +struct uwsgi_route_var *uwsgi_get_route_var(char *, uint16_t); +struct uwsgi_route_var *uwsgi_register_route_var(char *, char *(*)(struct wsgi_request *, char *, uint16_t, uint16_t *)); + +char *uwsgi_get_mime_type(char *, int, size_t *); + +void config_magic_table_fill(char *, char *[]); + +int uwsgi_blob_to_response(struct wsgi_request *, char *, size_t); +struct uwsgi_cron *uwsgi_cron_add(char *); +int uwsgi_is_full_http(struct uwsgi_buffer *); + +int uwsgi_http_date(time_t t, char *); + +int uwsgi_apply_transformations(struct wsgi_request *wsgi_req, char *, size_t); +int uwsgi_apply_final_transformations(struct wsgi_request *); +void uwsgi_free_transformations(struct wsgi_request *); +struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_transformation *), void *); + +void uwsgi_file_write_do(struct uwsgi_string_list *); + +int uwsgi_fd_is_safe(int); +void uwsgi_add_safe_fd(int); + +void uwsgi_ipcsem_clear(void); +char *uwsgi_str_to_hex(char *, size_t); + +// this 3 functions have been added 1.9.10 to allow plugins take the control over processes +void uwsgi_worker_run(void); +void uwsgi_mule_run(void); +void uwsgi_spooler_run(void); +void uwsgi_takeover(void); + +char *uwsgi_binary_path(void); + +int uwsgi_is_again(); +void uwsgi_disconnect(struct wsgi_request *); +int uwsgi_ready_fd(struct wsgi_request *); + +void uwsgi_envdir(char *); +void uwsgi_envdirs(struct uwsgi_string_list *); +void uwsgi_opt_envdir(char *, char *, void *); + +void uwsgi_add_reload_fds(); + +void uwsgi_check_emperor(void); +#ifdef UWSGI_AS_SHARED_LIBRARY +int uwsgi_init(int, char **, char **); +#endif + +int uwsgi_master_check_cron_death(int); +struct uwsgi_fsmon *uwsgi_register_fsmon(char *, void (*)(struct uwsgi_fsmon *), void *data); +int uwsgi_fsmon_event(int); +void uwsgi_fsmon_setup(); + +void uwsgi_exit(int) __attribute__ ((__noreturn__)); +void uwsgi_fallback_config(); + +struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *, uint64_t *, struct uwsgi_cache_item **); +void uwsgi_cache_rlock(struct uwsgi_cache *); +void uwsgi_cache_rwunlock(struct uwsgi_cache *); +char *uwsgi_cache_item_key(struct uwsgi_cache_item *); + +char *uwsgi_binsh(void); +int uwsgi_file_executable(char *); + +int uwsgi_mount(char *, char *, char *, char *, char *); +int uwsgi_umount(char *, char *); +int uwsgi_mount_hook(char *); +int uwsgi_umount_hook(char *); + +void uwsgi_hooks_run(struct uwsgi_string_list *, char *, int); +void uwsgi_register_hook(char *, int (*)(char *)); +struct uwsgi_hook *uwsgi_hook_by_name(char *); +void uwsgi_register_base_hooks(void); + +void uwsgi_setup_log_encoders(void); +void uwsgi_log_encoders_register_embedded(void); + +void uwsgi_register_log_encoder(char *, char *(*)(struct uwsgi_log_encoder *, char *, size_t, size_t *)); + +int uwsgi_accept(int); +void suspend_resume_them_all(int); + +void uwsgi_master_fifo_prepare(); +int uwsgi_master_fifo(); +int uwsgi_master_fifo_manage(int); + +void uwsgi_log_do_rotate(char *, char *, off_t, int); +void uwsgi_log_rotate(); +void uwsgi_log_reopen(); +void uwsgi_reload_workers(); +void uwsgi_reload_mules(); +void uwsgi_reload_spoolers(); +void uwsgi_chain_reload(); +void uwsgi_refork_master(); +void uwsgi_update_pidfiles(); +void gracefully_kill_them_all(int); +void uwsgi_brutally_reload_workers(); + +void uwsgi_cheaper_increase(); +void uwsgi_cheaper_decrease(); +void uwsgi_go_cheap(); + +char **uwsgi_split_quoted(char *, size_t, char *, size_t *); + +void uwsgi_master_manage_emperor_proxy(); +struct uwsgi_string_list *uwsgi_register_scheme(char *, char * (*)(char *, size_t *, int)); +void uwsgi_setup_schemes(void); + +struct uwsgi_string_list *uwsgi_check_scheme(char *); + +void uwsgi_remap_fd(int, char *); +void uwsgi_opt_exit(char *, char *, void *); +int uwsgi_check_mountpoint(char *); +void uwsgi_master_check_mountpoints(void); + +enum { + UWSGI_METRIC_COUNTER, + UWSGI_METRIC_GAUGE, + UWSGI_METRIC_ABSOLUTE, + UWSGI_METRIC_ALIAS, +}; + +struct uwsgi_metric_child; + +struct uwsgi_metric_collector { + char *name; + int64_t (*func)(struct uwsgi_metric *); + struct uwsgi_metric_collector *next; +}; + +struct uwsgi_metric_threshold { + int64_t value; + uint8_t reset; + int64_t reset_value; + int32_t rate; + char *alarm; + char *msg; + size_t msg_len; + time_t last_alarm; + struct uwsgi_metric_threshold *next; +}; + +struct uwsgi_metric { + char *name; + char *oid; + + size_t name_len; + size_t oid_len; + + // pre-computed snmp representation + char *asn; + size_t asn_len; + + // ABSOLUTE/COUNTER/GAUGE + uint8_t type; + + // this could be taken from a file storage and must be always added to value by the collector (default 0) + int64_t initial_value; + // the value of the metric (point to a shared memory area) + int64_t *value; + + // a custom blob you can attach to a metric + void *custom; + + // the collection frequency + uint32_t freq; + time_t last_update; + + // run this function to collect the value + struct uwsgi_metric_collector *collector; + // take the value from this pointer to a 64bit value + int64_t *ptr; + // get the initial value from this file, and store each update in it + char *filename; + + // pointer to memory mapped storage + char *map; + + // arguments for collectors + char *arg1; + char *arg2; + char *arg3; + + int64_t arg1n; + int64_t arg2n; + int64_t arg3n; + + struct uwsgi_metric_child *children; + struct uwsgi_metric_threshold *thresholds; + + struct uwsgi_metric *next; + + // allow to reset metrics after each push + uint8_t reset_after_push; +}; + +struct uwsgi_metric_child { + struct uwsgi_metric *um; + struct uwsgi_metric_child *next; +}; + +void uwsgi_setup_metrics(void); +void uwsgi_metrics_start_collector(void); + +int uwsgi_metric_set(char *, char *, int64_t); +int uwsgi_metric_inc(char *, char *, int64_t); +int uwsgi_metric_dec(char *, char *, int64_t); +int uwsgi_metric_mul(char *, char *, int64_t); +int uwsgi_metric_div(char *, char *, int64_t); +int64_t uwsgi_metric_get(char *, char *); +int64_t uwsgi_metric_getn(char *, size_t, char *, size_t); +int uwsgi_metric_set_max(char *, char *, int64_t); +int uwsgi_metric_set_min(char *, char *, int64_t); + +struct uwsgi_metric_collector *uwsgi_register_metric_collector(char *, int64_t (*)(struct uwsgi_metric *)); +struct uwsgi_metric *uwsgi_register_metric(char *, char *, uint8_t, char *, void *, uint32_t, void *); + +void uwsgi_metrics_collectors_setup(void); +struct uwsgi_metric *uwsgi_metric_find_by_name(char *); +struct uwsgi_metric *uwsgi_metric_find_by_namen(char *, size_t); +struct uwsgi_metric_child *uwsgi_metric_add_child(struct uwsgi_metric *, struct uwsgi_metric *); + +struct uwsgi_metric *uwsgi_metric_find_by_oid(char *); +struct uwsgi_metric *uwsgi_metric_find_by_oidn(char *, size_t); +struct uwsgi_metric *uwsgi_metric_find_by_asn(char *, size_t); + +int uwsgi_base128(struct uwsgi_buffer *, uint64_t, int); + +struct wsgi_request *find_wsgi_req_proto_by_fd(int); + +struct uwsgi_protocol *uwsgi_register_protocol(char *, void (*)(struct uwsgi_socket *)); + +void uwsgi_protocols_register(void); + +void uwsgi_build_plugin(char *dir); + +void uwsgi_sharedareas_init(); + +struct uwsgi_sharedarea *uwsgi_sharedarea_init(int); +struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *, uint64_t); +struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int, uint64_t, off_t); + +int64_t uwsgi_sharedarea_read(int, uint64_t, char *, uint64_t); +int uwsgi_sharedarea_write(int, uint64_t, char *, uint64_t); +int uwsgi_sharedarea_read64(int, uint64_t, int64_t *); +int uwsgi_sharedarea_write64(int, uint64_t, int64_t *); +int uwsgi_sharedarea_read8(int, uint64_t, int8_t *); +int uwsgi_sharedarea_write8(int, uint64_t, int8_t *); +int uwsgi_sharedarea_read16(int, uint64_t, int16_t *); +int uwsgi_sharedarea_write16(int, uint64_t, int16_t *); +int uwsgi_sharedarea_read32(int, uint64_t, int32_t *); +int uwsgi_sharedarea_write32(int, uint64_t, int32_t *); +int uwsgi_sharedarea_inc8(int, uint64_t, int8_t); +int uwsgi_sharedarea_inc16(int, uint64_t, int16_t); +int uwsgi_sharedarea_inc32(int, uint64_t, int32_t); +int uwsgi_sharedarea_inc64(int, uint64_t, int64_t); +int uwsgi_sharedarea_dec8(int, uint64_t, int8_t); +int uwsgi_sharedarea_dec16(int, uint64_t, int16_t); +int uwsgi_sharedarea_dec32(int, uint64_t, int32_t); +int uwsgi_sharedarea_dec64(int, uint64_t, int64_t); +int uwsgi_sharedarea_wait(int, int, int); +int uwsgi_sharedarea_unlock(int); +int uwsgi_sharedarea_rlock(int); +int uwsgi_sharedarea_wlock(int); +int uwsgi_sharedarea_update(int); + +struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int, uint64_t); +int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *, int, uint64_t, uint64_t); +int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *, int, uint64_t, uint64_t); + +void uwsgi_register_logchunks(void); + +void uwsgi_setup(int, char **, char **); +int uwsgi_run(void); + +int uwsgi_is_connected(int); +int uwsgi_pass_cred(int, char *, size_t); +int uwsgi_pass_cred2(int, char *, size_t, struct sockaddr *, size_t); +int uwsgi_recv_cred(int, char *, size_t, pid_t *, uid_t *, gid_t *); +ssize_t uwsgi_recv_cred2(int, char *, size_t, pid_t *, uid_t *, gid_t *); +int uwsgi_socket_passcred(int); + +void uwsgi_dump_worker(int, char *); +mode_t uwsgi_mode_t(char *, int *); + +int uwsgi_notify_socket_manage(int); +int uwsgi_notify_msg(char *, char *, size_t); +void vassal_sos(); + +int uwsgi_wait_for_fs(char *, int); +int uwsgi_wait_for_mountpoint(char *); +int uwsgi_wait_for_socket(char *); + +#ifdef __cplusplus +} +#endif diff --git a/.uwsgi_plugins_builder/uwsgiconfig.py b/.uwsgi_plugins_builder/uwsgiconfig.py new file mode 100644 index 00000000..22c9dd34 --- /dev/null +++ b/.uwsgi_plugins_builder/uwsgiconfig.py @@ -0,0 +1,1665 @@ +# uWSGI build system + +uwsgi_version = '2.0.18' + +import os +import re +import time +uwsgi_os = os.uname()[0] +uwsgi_os_k = re.split('[-+_]', os.uname()[2])[0] +uwsgi_os_v = os.uname()[3] +uwsgi_cpu = os.uname()[4] + +import sys +import subprocess +from threading import Thread,Lock +from optparse import OptionParser + +try: + from queue import Queue +except: + from Queue import Queue + +from distutils import sysconfig + +try: + import ConfigParser +except: + import configparser as ConfigParser + + +PY3 = sys.version_info[0] == 3 + +if uwsgi_os == 'Darwin': + GCC = os.environ.get('CC', 'clang') +else: + GCC = os.environ.get('CC', sysconfig.get_config_var('CC')) + if not GCC: + GCC = 'gcc' + +def get_preprocessor(): + if 'clang' in GCC: + return 'clang -xc core/clang_fake.c' + return 'cpp' + +CPP = os.environ.get('CPP', get_preprocessor()) + +try: + CPUCOUNT = int(os.environ.get('CPUCOUNT', -1)) +except: + CPUCOUNT = -1 + +if CPUCOUNT < 1: + try: + import multiprocessing + CPUCOUNT = multiprocessing.cpu_count() + except: + try: + CPUCOUNT = int(os.sysconf('SC_NPROCESSORS_ONLN')) + except: + CPUCOUNT = 1 + + +# force single cpu in cygwin mode +if uwsgi_os.startswith('CYGWIN'): + CPUCOUNT=1 + +binary_list = [] + +started_at = time.time() + +# this is used for reporting (at the end of the build) +# the server configuration +report = { + 'kernel': False, + 'execinfo': False, + 'ifaddrs': False, + 'locking': False, + 'event': False, + 'timer': False, + 'filemonitor': False, + 'pcre': False, + 'routing': False, + 'capabilities': False, + 'yaml': False, + 'json': False, + 'ssl': False, + 'xml': False, + 'debug': False, + 'plugin_dir': False, + 'zlib': False, + 'ucontext': False, +} + +verbose_build = False + +def print_compilation_output(default_str, verbose_str): + if verbose_build: + print(verbose_str) + elif default_str is not None: + print(default_str) + +compile_queue = None +print_lock = None +thread_compilers = [] + +def thread_compiler(num): + while True: + (objfile, cmdline) = compile_queue.get() + if objfile: + print_lock.acquire() + print_compilation_output("[thread %d][%s] %s" % (num, GCC, objfile), "[thread %d] %s" % (num, cmdline)) + print_lock.release() + ret = os.system(cmdline) + if ret != 0: + os._exit(1) + elif cmdline: + print_lock.acquire() + print(cmdline) + print_lock.release() + else: + return + + + + +def binarize(name): + return name.replace('/', '_').replace('.','_').replace('-','_') + +def spcall(cmd): + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,stderr=open('uwsgibuild.log','w')) + + if p.wait() == 0: + if sys.version_info[0] > 2: + return p.stdout.read().rstrip().decode() + return p.stdout.read().rstrip() + else: + return None + +# commodity function to remove -W* duplicates +def uniq_warnings(elements): + new_elements = [] + for element in elements: + if element.startswith('-W'): + if not element in new_elements: + new_elements.append(element) + else: + new_elements.append(element) + + return new_elements + +if uwsgi_version.endswith('-dev') and os.path.exists('%s/.git' % os.path.dirname(os.path.abspath( __file__ ))): + try: + uwsgi_version += '-%s' % spcall('git rev-parse --short HEAD') + except: + pass + + +def spcall2(cmd): + p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE) + + if p.wait() == 0: + if sys.version_info[0] > 2: + return p.stderr.read().rstrip().decode() + return p.stderr.read().rstrip() + else: + return None + + +def test_snippet(snippet): + """Compile a C snippet to see if features are available at build / link time.""" + if sys.version_info[0] >= 3 or (sys.version_info[0] == 2 and sys.version_info[1] > 5): + if not isinstance(snippet, bytes): + if PY3: + snippet = bytes(snippet, sys.getdefaultencoding()) + else: + snippet = bytes(snippet) + cmd = "{0} -xc - -o /dev/null".format(GCC) + else: + cmd = GCC + " -xc - -o /dev/null" + p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + p.communicate(snippet) + return p.returncode == 0 + + +def has_usable_ucontext(): + if uwsgi_os in ('OpenBSD', 'Haiku'): + return False + if uwsgi_os.startswith('CYGWIN'): + return False + if uwsgi_os == 'Darwin' and uwsgi_os_k.startswith('8'): + return False + if uwsgi_cpu[0:3] == 'arm': + return False + # check for ucontext.h functions definitions, musl has only declarations + return test_snippet("""#include +int main() +{ + ucontext_t uc; + getcontext(&uc); + return 0; +}""") + + +def spcall3(cmd): + p = subprocess.Popen(cmd, shell=True, stdin=open('/dev/null'), stderr=subprocess.PIPE, stdout=subprocess.PIPE) + + if p.wait() == 0: + if sys.version_info[0] > 2: + return p.stderr.read().rstrip().decode() + return p.stderr.read().rstrip() + else: + return None + + +def add_o(x): + if x == 'uwsgi': + x = 'main' + elif x.endswith('.a') or x.endswith('.o'): + return x + x = x + '.o' + return x + +def push_print(msg): + if not compile_queue: + print(msg) + else: + compile_queue.put((None, msg)) + +def push_command(objfile, cmdline): + if not compile_queue: + print_compilation_output("[%s] %s" % (GCC, objfile), cmdline) + ret = os.system(cmdline) + if ret != 0: + sys.exit(1) + else: + compile_queue.put((objfile, cmdline)) + + +def compile(cflags, last_cflags_ts, objfile, srcfile): + source_stat = os.stat(srcfile) + header_stat = os.stat('uwsgi.h') + try: + if os.environ.get('UWSGI_FORCE_REBUILD', None): + raise + if source_stat[8] >= last_cflags_ts: + raise + if header_stat[8] >= last_cflags_ts: + raise + object_stat = os.stat(objfile) + if object_stat[8] <= source_stat[8]: + raise + if object_stat[8] <= header_stat[8]: + raise + for profile in os.listdir('buildconf'): + profile_stat = os.stat('buildconf/%s' % profile) + if object_stat[8] <= profile_stat[8]: + raise + print("%s is up to date" % objfile) + return + except: + pass + cmdline = "%s -c %s -o %s %s" % (GCC, cflags, objfile, srcfile) + push_command(objfile, cmdline) + + +def build_uwsgi(uc, print_only=False, gcll=None): + + global print_lock, compile_queue, thread_compilers + + if CPUCOUNT > 1: + print_lock = Lock() + compile_queue = Queue(maxsize=CPUCOUNT) + for i in range(0,CPUCOUNT): + t = Thread(target=thread_compiler,args=(i,)) + t.daemon = True + t.start() + thread_compilers.append(t) + + if not gcll: + gcc_list, cflags, ldflags, libs = uc.get_gcll() + else: + gcc_list, cflags, ldflags, libs = gcll + + if 'UWSGI_EMBED_PLUGINS' in os.environ: + ep = uc.get('embedded_plugins') + if ep: + uc.set('embedded_plugins', ep + ',' + os.environ['UWSGI_EMBED_PLUGINS']) + else: + uc.set('embedded_plugins', os.environ['UWSGI_EMBED_PLUGINS']) + + if uc.get('embedded_plugins'): + ep = uc.get('embedded_plugins').split(',') + epc = "-DUWSGI_DECLARE_EMBEDDED_PLUGINS=\"" + eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\"" + for item in ep: + # allow name=path syntax + kv = item.split('=') + p = kv[0] + p = p.strip() + if not p or p == 'None': + continue + if p == 'ugreen': + if not report['ucontext']: + continue + epc += "UDEP(%s);" % p + eplc += "ULEP(%s);" % p + epc += "\"" + eplc += "\"" + + cflags.append(epc) + cflags.append(eplc) + + if print_only: + print(' '.join(cflags)) + sys.exit(0) + + if 'APPEND_CFLAGS' in os.environ: + cflags += os.environ['APPEND_CFLAGS'].split() + + print("detected CPU cores: %d" % CPUCOUNT) + print("configured CFLAGS: %s" % ' '.join(cflags)) + + if sys.version_info[0] >= 3: + import binascii + uwsgi_cflags = binascii.b2a_hex(' '.join(cflags).encode('ascii')).decode('ascii') + else: + uwsgi_cflags = ' '.join(cflags).encode('hex') + + last_cflags_ts = 0 + + if os.path.exists('uwsgibuild.lastcflags'): + ulc = open('uwsgibuild.lastcflags','r') + last_cflags = ulc.read() + ulc.close() + if uwsgi_cflags != last_cflags: + os.environ['UWSGI_FORCE_REBUILD'] = '1' + else: + last_cflags_ts = os.stat('uwsgibuild.lastcflags')[8] + + + ulc = open('uwsgibuild.lastcflags','w') + ulc.write(uwsgi_cflags) + ulc.close() + + # embed uwsgi.h in the server binary. It increases the binary size, but will be very useful + # for various tricks (like cffi integration) + # if possibile, the blob is compressed + if sys.version_info[0] >= 3: + uwsgi_dot_h_content = open('uwsgi.h', 'rb').read() + else: + uwsgi_dot_h_content = open('uwsgi.h').read() + if report['zlib']: + import zlib + # maximum level of compression + uwsgi_dot_h_content = zlib.compress(uwsgi_dot_h_content, 9) + if sys.version_info[0] >= 3: + import binascii + uwsgi_dot_h = binascii.b2a_hex(uwsgi_dot_h_content).decode('ascii') + else: + uwsgi_dot_h = uwsgi_dot_h_content.encode('hex') + open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h); + gcc_list.append('core/dot_h') + + # embed uwsgiconfig.py in the server binary. It increases the binary size, but will be very useful + # if possibile, the blob is compressed + if sys.version_info[0] >= 3: + uwsgi_config_py_content = open('uwsgiconfig.py', 'rb').read() + else: + uwsgi_config_py_content = open('uwsgiconfig.py').read() + if report['zlib']: + import zlib + # maximum level of compression + uwsgi_config_py_content = zlib.compress(uwsgi_config_py_content, 9) + if sys.version_info[0] >= 3: + import binascii + uwsgi_config_py = binascii.b2a_hex(uwsgi_config_py_content).decode('ascii') + else: + uwsgi_config_py = uwsgi_config_py_content.encode('hex') + open('core/config_py.c', 'w').write('char *uwsgi_config_py = "%s";\n' % uwsgi_config_py); + gcc_list.append('core/config_py') + + additional_sources = os.environ.get('UWSGI_ADDITIONAL_SOURCES') + if not additional_sources: + additional_sources = uc.get('additional_sources') + if additional_sources: + for item in additional_sources.split(','): + gcc_list.append(item) + + if uc.filename.endswith('coverity.ini'): + cflags.append('-DUWSGI_CFLAGS=\\"\\"') + else: + cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags) + build_date = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) + cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S", time.gmtime(build_date))) + + post_build = [] + + push_print("*** uWSGI compiling server core ***") + for file in gcc_list: + objfile = file + if objfile == 'uwsgi': + objfile = 'main' + if not objfile.endswith('.a') and not objfile.endswith('.o'): + if objfile.endswith('.c') or objfile.endswith('.cc') or objfile.endswith('.m') or objfile.endswith('.go'): + if objfile.endswith('.go'): + cflags.append('-Wno-error') + compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file) + if objfile.endswith('.go'): + cflags.pop() + else: + if objfile == 'core/dot_h': + cflags.append('-g') + compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file + '.c') + if objfile == 'core/dot_h': + cflags.pop() + + if uc.get('embedded_plugins'): + ep = uc.get('embedded_plugins').split(',') + + if len(ep) > 0: + push_print("*** uWSGI compiling embedded plugins ***") + for item in ep: + # allows name=path syntax + kv = item.split('=') + if len(kv) > 1: + p = kv[1] + p = p.strip() + if p.startswith('http://') or p.startswith('https://') or p.startswith('git://') or p.startswith('ssh://'): + git_dir = p.split('/').pop() + if not os.path.isdir(git_dir): + if os.system('git clone %s' % p) != 0: + sys.exit(1) + else: + if os.system('cd %s ; git pull' % git_dir) != 0: + sys.exit(1) + p = git_dir + path = os.path.abspath(p) + else: + p = kv[0] + p = p.strip() + path = 'plugins/%s' % p + + if not p or p == 'None': + continue + + if p == 'ugreen': + if not report['ucontext']: + continue + + path = path.rstrip('/') + + up = {} + + if os.path.isfile(path): + bname = os.path.basename(path) + # override path + path = os.path.dirname(path) + up['GCC_LIST'] = [bname] + up['NAME'] = bname.split('.')[0] + if not path: path = '.' + elif os.path.isdir(path): + try: + execfile('%s/uwsgiplugin.py' % path, up) + except: + f = open('%s/uwsgiplugin.py' % path) + exec(f.read(), up) + f.close() + else: + print("Error: plugin '%s' not found" % p) + sys.exit(1) + + p_cflags = cflags[:] + try: + p_cflags += up['CFLAGS'] + except: + pass + + if uwsgi_os.startswith('CYGWIN'): + try: + p_cflags.remove('-fstack-protector') + except: + pass + + if GCC in ('clang',): + try: + p_cflags.remove('-fno-fast-math') + p_cflags.remove('-ggdb3') + except: + pass + + try: + p_cflags.remove('-Wdeclaration-after-statement') + except: + pass + + try: + p_cflags.remove('-Werror=declaration-after-statement') + except: + pass + + try: + p_cflags.remove('-Wwrite-strings') + except: + pass + + try: + p_cflags.remove('-Werror=write-strings') + except: + pass + + try: + if up['post_build']: + post_build.append(up['post_build']) + except: + pass + + for cfile in up['GCC_LIST']: + if cfile.endswith('.a'): + gcc_list.append(cfile) + elif cfile.endswith('.o'): + gcc_list.append('%s/%s' % (path, cfile)) + elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.go') and not cfile.endswith('.m'): + compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts, + path + '/' + cfile + '.o', path + '/' + cfile + '.c') + gcc_list.append('%s/%s' % (path, cfile)) + else: + if cfile.endswith('.go'): + p_cflags.append('-Wno-error') + compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts, + path + '/' + cfile + '.o', path + '/' + cfile) + gcc_list.append('%s/%s' % (path, cfile)) + for bfile in up.get('BINARY_LIST', []): + try: + binary_link_cmd = "ld -r -b binary -o %s/%s.o %s/%s" % (path, bfile[1], path, bfile[1]) + print(binary_link_cmd) + if os.system(binary_link_cmd) != 0: + raise Exception('unable to link binary file') + for kind in ('start','end'): + objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=%s_%s %s/%s.o" % (binarize('%s/%s' % (path, bfile[1])), kind, bfile[0], kind, path, bfile[1]) + print(objcopy_cmd) + if os.system(objcopy_cmd) != 0: + raise Exception('unable to link binary file') + gcc_list.append('%s/%s.o' % (path, bfile[1])) + except: + pass + + try: + libs += up['LIBS'] + except: + pass + + if not 'LDFLAGS' in up: + up['LDFLAGS'] = [] + + if uwsgi_os == 'Darwin': + found_arch = False + sanitized_ldflags = [] + for flag in up['LDFLAGS']: + if flag == '-arch': + found_arch = True + continue + if found_arch: + found_arch = False + continue + sanitized_ldflags.append(flag) + ldflags += sanitized_ldflags + else: + ldflags += up['LDFLAGS'] + + if uc.get('plugins'): + + plugins = uc.get('plugins').split(',') + if len(plugins) > 0: + push_print("*** uWSGI building plugins ***") + + for p in plugins: + p = p.strip() + push_print("*** building plugin: %s ***" % p) + build_plugin("plugins/%s" % p, uc, cflags, ldflags, libs) + + bin_name = os.environ.get('UWSGI_BIN_NAME', uc.get('bin_name')) + + if uc.embed_config: + gcc_list.append("%s.o" % binarize(uc.embed_config)) + for ef in binary_list: + gcc_list.append("%s.o" % ef) + + if compile_queue: + for t in thread_compilers: + compile_queue.put((None, None)) + for t in thread_compilers: + t.join() + + print("*** uWSGI linking ***") + ldline = "%s -o %s %s %s %s" % (GCC, bin_name, ' '.join(uniq_warnings(ldflags)), + ' '.join(map(add_o, gcc_list)), ' '.join(uniq_warnings(libs))) + print(ldline) + ret = os.system(ldline) + if ret != 0: + print("*** error linking uWSGI ***") + sys.exit(1) + + print("################# uWSGI configuration #################") + print("") + for report_key in report: + print("%s = %s" % (report_key, report[report_key])) + print("") + print("############## end of uWSGI configuration #############") + + print("total build time: %d seconds" % (time.time() - started_at)) + + if bin_name.find("/") < 0: + bin_name = './' + bin_name + if uc.get('as_shared_library'): + print("*** uWSGI shared library (%s) is ready, move it to a library directory ***" % bin_name) + else: + print("*** uWSGI is ready, launch it with %s ***" % bin_name) + + for pb in post_build: + pb(uc) + +def open_profile(filename): + if filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://'): + wrapped = False + try: + import urllib2 + except: + import urllib.request + wrapped = True + + if wrapped: + import io + return io.TextIOWrapper(urllib.request.urlopen(filename), encoding='utf-8') + return urllib2.urlopen(filename) + return open(filename) + +class uConf(object): + + def __init__(self, filename, mute=False): + global GCC + + self.filename = filename + self.config = ConfigParser.ConfigParser() + if not mute: + print("using profile: %s" % filename) + + if os.path.exists('uwsgibuild.lastprofile'): + ulp = open('uwsgibuild.lastprofile','r') + last_profile = ulp.read() + ulp.close() + if last_profile != filename: + os.environ['UWSGI_FORCE_REBUILD'] = '1' + + ulp = open('uwsgibuild.lastprofile', 'w') + ulp.write(filename) + ulp.close() + + if hasattr(self.config, 'read_file'): + self.config.read_file(open_profile(filename)) + else: + self.config.readfp(open_profile(filename)) + self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor', + 'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks', 'core/fifo', + 'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config', + 'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron', 'core/hooks', + 'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked', + 'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon', 'core/mount', + 'core/metrics', 'core/plugins_builder', 'core/sharedarea', + 'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi'] + # add protocols + self.gcc_list.append('proto/base') + self.gcc_list.append('proto/uwsgi') + self.gcc_list.append('proto/http') + self.gcc_list.append('proto/fastcgi') + self.gcc_list.append('proto/scgi') + self.gcc_list.append('proto/puwsgi') + self.include_path = [] + + if 'UWSGI_INCLUDES' in os.environ: + self.include_path += os.environ['UWSGI_INCLUDES'].split(',') + + + self.cflags = ['-O2', '-I.', '-Wall', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split() + self.get('cflags','').split() + + report['kernel'] = uwsgi_os + + if uwsgi_os == 'Linux': + if uwsgi_cpu != 'ia64': + self.gcc_list.append('lib/linux_ns') + try: + lk_ver = uwsgi_os_k.split('.') + if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]) <= 9: + self.cflags.append('-DOBSOLETE_LINUX_KERNEL') + report['kernel'] = 'Old Linux' + except: + pass + + if uwsgi_os == 'GNU': + self.cflags.append('-D__HURD__') + + gcc_version = spcall("%s -dumpversion" % GCC) + if not gcc_version and GCC.startswith('gcc'): + if uwsgi_os == 'Darwin': + GCC = 'llvm-' + GCC + else: + GCC = 'gcc' + gcc_version = spcall("%s -dumpversion" % GCC) + + try: + add_it = False + cpp_include_list = str(spcall3("%s -v" % CPP)).split("\n") + for line in cpp_include_list: + if line.startswith('#include <...> search starts here:'): + add_it = True + elif line.startswith('End of search list.'): + add_it = False + elif add_it: + self.include_path.append(line.strip().split()[0]) + + if not self.include_path: + raise + except: + self.include_path = ['/usr/include', '/usr/local/include'] + + additional_include_paths = self.get('additional_include_paths') + if additional_include_paths: + for ipath in additional_include_paths.split(): + self.include_path.append(ipath) + + if 'UWSGI_REMOVE_INCLUDES' in os.environ: + for inc in os.environ['UWSGI_REMOVE_INCLUDES'].split(','): + try: + self.include_path.remove(inc) + except: + pass + + + if not mute: + print("detected include path: %s" % self.include_path) + + try: + gcc_version_components = gcc_version.split('.') + gcc_major = int(gcc_version_components[0]) + if len(gcc_version_components) > 1: + gcc_minor = int(gcc_version_components[1]) + else: + # gcc 5.0 is represented as simply "5" + gcc_minor = 0 + except: + raise Exception("you need a C compiler to build uWSGI") + if (sys.version_info[0] == 2) or (gcc_major < 4) or (gcc_major == 4 and gcc_minor < 3): + self.cflags = self.cflags + ['-fno-strict-aliasing'] + # add -fno-strict-aliasing only on python2 and gcc < 4.3 + if gcc_major >= 4: + self.cflags = self.cflags + [ '-Wextra', '-Wno-unused-parameter', '-Wno-missing-field-initializers' ] + if gcc_major == 4 and gcc_minor < 9: + self.cflags.append('-Wno-format -Wno-format-security') + + self.ldflags = os.environ.get("LDFLAGS", "").split() + self.libs = ['-lpthread', '-lm', '-rdynamic'] + if uwsgi_os in ('Linux', 'GNU', 'GNU/kFreeBSD'): + self.libs.append('-ldl') + if uwsgi_os == 'GNU/kFreeBSD': + self.cflags.append('-D__GNU_kFreeBSD__') + self.libs.append('-lbsd') + + # check for inherit option + inherit = self.get('inherit') + if inherit: + if not '/' in inherit: + inherit = 'buildconf/%s' % inherit + + if not inherit.endswith('.ini'): + inherit = '%s.ini' % inherit + + interpolations = {} + for option in self.config.options('uwsgi'): + interpolations[option] = self.get(option, default='') + iconfig = ConfigParser.ConfigParser(interpolations) + if hasattr(self.config, 'read_file'): + iconfig.read_file(open_profile(inherit)) + else: + iconfig.readfp(open_profile(inherit)) + + for opt in iconfig.options('uwsgi'): + if not self.config.has_option('uwsgi', opt): + self.set(opt, iconfig.get('uwsgi', opt)) + elif self.get(opt): + if self.get(opt).startswith('+'): + self.set(opt, iconfig.get('uwsgi', opt) + self.get(opt)[1:]) + elif self.get(opt) == 'null': + self.config.remove_option('uwsgi', opt) + + + def set(self, key, value): + self.config.set('uwsgi',key, value) + + def get(self,key,default=None): + try: + value = self.config.get('uwsgi', key) + if value == "" or value == "false": + return default + return value + except: + if default is not None: + return default + return None + + def depends_on(self, what, dep): + for d in dep: + if not self.get(d): + print("%s needs %s support." % (what, d)) + sys.exit(1) + + def has_include(self, what): + for include in self.include_path: + if os.path.exists("%s/%s" %(include, what)): + return True + return False + + def get_gcll(self): + + global uwsgi_version + + kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'] + + if 'UWSGI_PROFILE_OVERRIDE' in os.environ: + for item in os.environ['UWSGI_PROFILE_OVERRIDE'].split(';'): + k,v = item.split('=', 1) + self.set(k, v) + + if 'UWSGI_AS_LIB' in os.environ: + self.set('as_shared_library', 'true') + self.set('bin_name', os.environ['UWSGI_AS_LIB']) + + if self.has_include('ifaddrs.h'): + self.cflags.append('-DUWSGI_HAS_IFADDRS') + report['ifaddrs'] = True + + if uwsgi_os in ('FreeBSD', 'DragonFly', 'OpenBSD'): + if self.has_include('execinfo.h') or os.path.exists('/usr/local/include/execinfo.h'): + if os.path.exists('/usr/local/include/execinfo.h'): + self.cflags.append('-I/usr/local/include') + self.ldflags.append('-L/usr/local/lib') + self.cflags.append('-DUWSGI_HAS_EXECINFO') + self.libs.append('-lexecinfo') + report['execinfo'] = True + + if uwsgi_os == 'GNU/kFreeBSD': + if self.has_include('execinfo.h'): + self.cflags.append('-DUWSGI_HAS_EXECINFO') + report['execinfo'] = True + + if self.has_include('zlib.h'): + self.cflags.append('-DUWSGI_ZLIB') + self.libs.append('-lz') + self.gcc_list.append('core/zlib') + report['zlib'] = True + + if uwsgi_os == 'OpenBSD': + try: + obsd_major = uwsgi_os_k.split('.')[0] + obsd_minor = uwsgi_os_k.split('.')[1] + obsd_ver = int(obsd_major + obsd_minor) + if obsd_ver > 50: + self.cflags.append('-DUWSGI_NEW_OPENBSD') + report['kernel'] = 'New OpenBSD' + except: + pass + + if uwsgi_os == 'SunOS': + self.libs.append('-lsendfile') + self.libs.append('-lrt') + self.gcc_list.append('lib/sun_fixes') + self.ldflags.append('-L/lib') + if not uwsgi_os_v.startswith('Nexenta'): + self.libs.remove('-rdynamic') + + if uwsgi_os == 'GNU/kFreeBSD': + if self.has_include('kvm.h'): + kvm_list.append('GNU/kFreeBSD') + + if uwsgi_os in kvm_list: + self.libs.append('-lkvm') + + if uwsgi_os == 'Haiku': + self.libs.remove('-rdynamic') + self.libs.remove('-lpthread') + self.libs.append('-lroot') + + if uwsgi_os == 'Darwin': + if uwsgi_os_k.startswith('8'): + self.cflags.append('-DUNSETENV_VOID') + self.cflags.append('-DNO_SENDFILE') + self.cflags.append('-DNO_EXECINFO') + self.cflags.append('-DOLD_REALPATH') + self.cflags.append('-mmacosx-version-min=10.5') + if GCC in ('clang',): + self.libs.remove('-rdynamic') + + # compile extras + extras = self.get('extras', None) + if extras: + for extra in extras.split(','): + self.gcc_list.append(extra) + + # check for usable ucontext + report['ucontext'] = has_usable_ucontext() + + # set locking subsystem + locking_mode = self.get('locking','auto') + + if locking_mode == 'auto': + if uwsgi_os == 'Linux' or uwsgi_os == 'SunOS': + locking_mode = 'pthread_mutex' + # FreeBSD umtx is still not ready for process shared locking + # starting from FreeBSD 9 posix semaphores can be shared between processes + elif uwsgi_os in ('FreeBSD', 'GNU/kFreeBSD'): + try: + fbsd_major = int(uwsgi_os_k.split('.')[0]) + if fbsd_major >= 9: + locking_mode = 'posix_sem' + except: + pass + elif uwsgi_os == 'GNU': + locking_mode = 'posix_sem' + elif uwsgi_os == 'Darwin': + locking_mode = 'osx_spinlock' + elif uwsgi_os.startswith('CYGWIN'): + locking_mode = 'windows_mutex' + + if locking_mode == 'pthread_mutex': + self.cflags.append('-DUWSGI_LOCK_USE_MUTEX') + # FreeBSD umtx is still not ready for process shared locking + elif locking_mode == 'posix_sem': + self.cflags.append('-DUWSGI_LOCK_USE_POSIX_SEM') + elif locking_mode == 'osx_spinlock': + self.cflags.append('-DUWSGI_LOCK_USE_OSX_SPINLOCK') + elif locking_mode == 'windows_mutex': + self.cflags.append('-DUWSGI_LOCK_USE_WINDOWS_MUTEX') + else: + self.cflags.append('-DUWSGI_IPCSEM_ATEXIT') + + if locking_mode == 'auto': + report['locking'] = 'sysv semaphores' + else: + report['locking'] = locking_mode + + # set event subsystem + event_mode = self.get('event','auto') + + if event_mode == 'auto': + if uwsgi_os == 'Linux': + event_mode = 'epoll' + if uwsgi_os == 'SunOS': + event_mode = 'devpoll' + sun_major, sun_minor = uwsgi_os_k.split('.') + if int(sun_major) >= 5: + if int(sun_minor) >= 10: + event_mode = 'port' + elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'): + event_mode = 'kqueue' + elif uwsgi_os.startswith('CYGWIN') or uwsgi_os == 'GNU': + event_mode = 'poll' + + if event_mode == 'epoll': + self.cflags.append('-DUWSGI_EVENT_USE_EPOLL') + elif event_mode == 'kqueue': + self.cflags.append('-DUWSGI_EVENT_USE_KQUEUE') + elif event_mode == 'devpoll': + self.cflags.append('-DUWSGI_EVENT_USE_DEVPOLL') + elif event_mode == 'port': + self.cflags.append('-DUWSGI_EVENT_USE_PORT') + elif event_mode == 'poll': + self.cflags.append('-DUWSGI_EVENT_USE_POLL') + + report['event'] = event_mode + + # set timer subsystem + timer_mode = self.get('timer','auto') + + if timer_mode == 'auto': + if uwsgi_os == 'Linux': + k_all = uwsgi_os_k.split('.') + k_base = k_all[0] + k_major = k_all[1] + if len(k_all) > 2: + k_minor = k_all[2] + else: + k_minor = 0 + if int(k_base) > 2: + timer_mode = 'timerfd' + elif int(k_minor) >= 25: + timer_mode = 'timerfd' + else: + timer_mode = 'none' + + elif uwsgi_os == 'SunOS': + sun_major, sun_minor = uwsgi_os_k.split('.') + if int(sun_major) >= 5: + if int(sun_minor) >= 10: + timer_mode = 'port' + + elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'): + timer_mode = 'kqueue' + + if timer_mode == 'timerfd': + self.cflags.append('-DUWSGI_EVENT_TIMER_USE_TIMERFD') + if not self.has_include('sys/timerfd.h'): + self.cflags.append('-DUWSGI_EVENT_TIMER_USE_TIMERFD_NOINC') + elif timer_mode == 'kqueue': + self.cflags.append('-DUWSGI_EVENT_TIMER_USE_KQUEUE') + elif timer_mode == 'port': + self.cflags.append('-DUWSGI_EVENT_TIMER_USE_PORT') + else: + self.cflags.append('-DUWSGI_EVENT_TIMER_USE_NONE') + + report['timer'] = timer_mode + + # set filemonitor subsystem + filemonitor_mode = self.get('filemonitor','auto') + + if filemonitor_mode == 'auto': + if uwsgi_os == 'Linux': + filemonitor_mode = 'inotify' + elif uwsgi_os == 'SunOS': + sun_major, sun_minor = uwsgi_os_k.split('.') + if int(sun_major) >= 5: + if int(sun_minor) >= 10: + filemonitor_mode = 'port' + elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'): + filemonitor_mode = 'kqueue' + + if filemonitor_mode == 'inotify': + self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY') + elif filemonitor_mode == 'kqueue': + self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_KQUEUE') + elif filemonitor_mode == 'port': + self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_PORT') + else: + self.cflags.append('-DUWSGI_EVENT_FILEMONITOR_USE_NONE') + + + report['filemonitor'] = filemonitor_mode + + if self.get('malloc_implementation') != 'libc': + if self.get('malloc_implementation') == 'tcmalloc': + self.libs.append('-ltcmalloc') + if self.get('malloc_implementation') == 'jemalloc': + self.libs.append('-ljemalloc') + + report['malloc'] = self.get('malloc_implementation') + + + if self.get('as_shared_library'): + self.ldflags.append('-shared') + # on cygwin we do not need PIC (it is implicit) + if not uwsgi_os.startswith('CYGWIN'): + self.ldflags.append('-fPIC') + self.cflags.append('-fPIC') + self.cflags.append('-DUWSGI_AS_SHARED_LIBRARY') + if uwsgi_os == 'Darwin': + self.ldflags.append('-dynamiclib') + self.ldflags.append('-undefined dynamic_lookup') + + if self.get('blacklist'): + self.cflags.append('-DUWSGI_BLACKLIST="\\"%s\\""' % self.get('blacklist')) + + if self.get('whitelist'): + self.cflags.append('-DUWSGI_WHITELIST="\\"%s\\""' % self.get('whitelist')) + + has_pcre = False + + # re-enable after pcre fix + if self.get('pcre'): + if self.get('pcre') == 'auto': + pcreconf = spcall('pcre-config --libs') + if pcreconf: + self.libs.append(pcreconf) + pcreconf = spcall("pcre-config --cflags") + self.cflags.append(pcreconf) + self.gcc_list.append('core/regexp') + self.cflags.append("-DUWSGI_PCRE") + has_pcre = True + + else: + pcreconf = spcall('pcre-config --libs') + if pcreconf is None: + print("*** libpcre headers unavailable. uWSGI build is interrupted. You have to install pcre development package or disable pcre") + sys.exit(1) + else: + self.libs.append(pcreconf) + pcreconf = spcall("pcre-config --cflags") + self.cflags.append(pcreconf) + self.gcc_list.append('core/regexp') + self.cflags.append("-DUWSGI_PCRE") + has_pcre = True + + if has_pcre: + report['pcre'] = True + + if self.get('routing'): + if self.get('routing') == 'auto': + if has_pcre: + self.gcc_list.append('core/routing') + self.cflags.append("-DUWSGI_ROUTING") + report['routing'] = True + else: + self.gcc_list.append('core/routing') + self.cflags.append("-DUWSGI_ROUTING") + report['routing'] = True + + + if self.has_include('sys/capability.h') and uwsgi_os == 'Linux': + self.cflags.append("-DUWSGI_CAP") + self.libs.append('-lcap') + report['capabilities'] = True + + if self.has_include('uuid/uuid.h'): + self.cflags.append("-DUWSGI_UUID") + if uwsgi_os in ('Linux', 'GNU', 'GNU/kFreeBSD') or uwsgi_os.startswith('CYGWIN') or os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'): + self.libs.append('-luuid') + + if self.get('append_version'): + if not self.get('append_version').startswith('-'): + uwsgi_version += '-' + uwsgi_version += self.get('append_version') + + + if uwsgi_os in ('FreeBSD','GNU/kFreeBSD') and self.has_include('jail.h'): + self.cflags.append('-DUWSGI_HAS_FREEBSD_LIBJAIL') + self.libs.append('-ljail') + + self.embed_config = None + + if uwsgi_os not in ('Darwin',): + self.embed_config = os.environ.get('UWSGI_EMBED_CONFIG') + if not self.embed_config: + self.embed_config = self.get('embed_config') + if self.embed_config: + binary_link_cmd = "ld -r -b binary -o %s.o %s" % (binarize(self.embed_config), self.embed_config) + print(binary_link_cmd) + os.system(binary_link_cmd) + self.cflags.append("-DUWSGI_EMBED_CONFIG=_binary_%s_start" % binarize(self.embed_config)) + self.cflags.append("-DUWSGI_EMBED_CONFIG_END=_binary_%s_end" % binarize(self.embed_config)) + embed_files = os.environ.get('UWSGI_EMBED_FILES') + if not embed_files: + embed_files = self.get('embed_files') + if embed_files: + for ef in embed_files.split(','): + ef_parts = ef.split('=') + symbase = None + if len(ef_parts) > 1: + ef = ef_parts[1] + symbase = ef_parts[0] + if os.path.isdir(ef): + for directory, directories, files in os.walk(ef): + for f in files: + fname = "%s/%s" % (directory, f) + binary_link_cmd = "ld -r -b binary -o %s.o %s" % (binarize(fname), fname) + print(binary_link_cmd) + os.system(binary_link_cmd) + if symbase: + for kind in ('start','end'): + objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=_binary_%s%s_%s build/%s.o" % (binarize(fname), kind, binarize(symbase), binarize(fname[len(ef):]), kind, binarize(fname)) + print(objcopy_cmd) + os.system(objcopy_cmd) + binary_list.append(binarize(fname)) + else: + binary_link_cmd = "ld -r -b binary -o %s.o %s" % (binarize(ef), ef) + print(binary_link_cmd) + os.system(binary_link_cmd) + binary_list.append(binarize(ef)) + if symbase: + for kind in ('start','end'): + objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=_binary_%s_%s build/%s.o" % (binarize(ef), kind, binarize(symbase), kind, binarize(ef)) + print(objcopy_cmd) + os.system(objcopy_cmd) + + + + self.cflags.append('-DUWSGI_VERSION="\\"' + uwsgi_version + '\\""') + + uver_whole = uwsgi_version.split('-', 1) + if len(uver_whole) == 1: + uver_custom = '' + else: + uver_custom = uver_whole[1] + + uver_dots = uver_whole[0].split('.') + + uver_base = uver_dots[0] + uver_maj = uver_dots[1] + uver_min = '0' + uver_rev = '0' + + if len(uver_dots) > 2: + uver_min = uver_dots[2] + + if len(uver_dots) > 3: + uver_rev = uver_dots[3] + + + self.cflags.append('-DUWSGI_VERSION_BASE="' + uver_base + '"') + self.cflags.append('-DUWSGI_VERSION_MAJOR="' + uver_maj + '"') + self.cflags.append('-DUWSGI_VERSION_MINOR="' + uver_min + '"') + self.cflags.append('-DUWSGI_VERSION_REVISION="' + uver_rev + '"') + self.cflags.append('-DUWSGI_VERSION_CUSTOM="\\"' + uver_custom + '\\""') + + if self.get('yaml'): + self.cflags.append("-DUWSGI_YAML") + self.gcc_list.append('core/yaml') + report['yaml'] = 'embedded' + if self.get('yaml') == 'libyaml': + self.cflags.append("-DUWSGI_LIBYAML") + self.libs.append('-lyaml') + report['yaml'] = 'libyaml' + + if self.get('json'): + if self.get('json') in ('auto', 'true'): + jsonconf = spcall("pkg-config --cflags jansson") + if jsonconf: + self.cflags.append(jsonconf) + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append(spcall("pkg-config --libs jansson")) + report['json'] = 'jansson' + elif self.has_include('jansson.h'): + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append('-ljansson') + report['json'] = 'jansson' + else: + jsonconf = spcall("pkg-config --cflags yajl") + if jsonconf: + if jsonconf.endswith('include/yajl'): + jsonconf = jsonconf.rstrip('yajl') + self.cflags.append(jsonconf) + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append(spcall("pkg-config --libs yajl")) + self.cflags.append("-DUWSGI_JSON_YAJL") + report['json'] = 'yajl' + elif self.get('json') == 'true': + print("*** jansson and yajl headers unavailable. uWSGI build is interrupted. You have to install jansson or yajl development headers or disable JSON") + sys.exit(1) + elif self.get('json') == 'jansson': + jsonconf = spcall("pkg-config --cflags jansson") + if jsonconf: + self.cflags.append(jsonconf) + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append(spcall("pkg-config --libs jansson")) + report['json'] = 'jansson' + elif self.has_include('jansson.h'): + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append('-ljansson') + report['json'] = 'jansson' + else: + print("*** jansson headers unavailable. uWSGI build is interrupted. You have to install jansson development package or use yajl or disable JSON") + sys.exit(1) + elif self.get('json') == 'yajl': + jsonconf = spcall("pkg-config --cflags yajl") + if jsonconf: + self.cflags.append(jsonconf) + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append(spcall("pkg-config --libs yajl")) + self.cflags.append("-DUWSGI_JSON_YAJL") + report['json'] = 'yajl' + elif self.has_include('yajl/yajl_tree.h'): + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append('-lyajl') + self.cflags.append("-DUWSGI_JSON_YAJL") + report['json'] = 'yajl' + elif self.has_include('yajl/yajl_parse.h'): + self.cflags.append("-DUWSGI_JSON") + self.gcc_list.append('core/json') + self.libs.append('-lyajl') + self.cflags.append("-DUWSGI_JSON_YAJL_OLD") + report['json'] = 'yajl_old' + else: + print("*** yajl headers unavailable. uWSGI build is interrupted. You have to install yajl development package or use jansson or disable JSON") + sys.exit(1) + + + if self.get('ssl'): + if self.get('ssl') == 'auto': + if self.has_include('openssl/ssl.h'): + self.cflags.append("-DUWSGI_SSL") + self.libs.append('-lssl') + self.libs.append('-lcrypto') + self.gcc_list.append('core/ssl') + self.gcc_list.append('core/legion') + report['ssl'] = True + else: + self.cflags.append("-DUWSGI_SSL") + self.libs.append('-lssl') + self.libs.append('-lcrypto') + self.gcc_list.append('core/ssl') + self.gcc_list.append('core/legion') + report['ssl'] = True + + if self.get('xml'): + if self.get('xml') == 'auto': + xmlconf = spcall('xml2-config --libs') + if xmlconf and uwsgi_os != 'Darwin': + self.libs.append(xmlconf) + xmlconf = spcall("xml2-config --cflags") + self.cflags.append(xmlconf) + self.cflags.append("-DUWSGI_XML -DUWSGI_XML_LIBXML2") + self.gcc_list.append('core/xmlconf') + report['xml'] = 'libxml2' + elif self.has_include('expat.h'): + self.cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT") + self.libs.append('-lexpat') + self.gcc_list.append('core/xmlconf') + report['xml'] = 'expat' + elif self.get('xml') == 'libxml2': + xmlconf = spcall('xml2-config --libs') + if xmlconf is None: + print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML") + sys.exit(1) + else: + self.libs.append(xmlconf) + xmlconf = spcall("xml2-config --cflags") + if xmlconf is None: + print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML") + sys.exit(1) + else: + self.cflags.append(xmlconf) + self.cflags.append("-DUWSGI_XML -DUWSGI_XML_LIBXML2") + self.gcc_list.append('core/xmlconf') + report['xml'] = 'libxml2' + elif self.get('xml') == 'expat': + self.cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT") + self.libs.append('-lexpat') + self.gcc_list.append('core/xmlconf') + report['xml'] = 'expat' + + if self.get('plugin_dir'): + self.cflags.append('-DUWSGI_PLUGIN_DIR="\\"%s\\""' % self.get('plugin_dir')) + report['plugin_dir'] = self.get('plugin_dir') + + if self.get('debug'): + self.cflags.append("-DUWSGI_DEBUG") + self.cflags.append("-g") + report['debug'] = True + + if self.get('unbit'): + self.cflags.append("-DUNBIT") + + return self.gcc_list, self.cflags, self.ldflags, self.libs + +def build_plugin(path, uc, cflags, ldflags, libs, name = None): + path = path.rstrip('/') + + plugin_started_at = time.time() + + up = {} + + if path.startswith('http://') or path.startswith('https://') or path.startswith('git://') or path.startswith('ssh://'): + git_dir = path.split('/').pop() + if not os.path.isdir(git_dir): + if os.system('git clone %s' % path) != 0: + sys.exit(1) + else: + if os.system('cd %s ; git pull' % git_dir) != 0: + sys.exit(1) + path = os.path.abspath(git_dir) + + if os.path.isfile(path): + bname = os.path.basename(path) + # override path + path = os.path.dirname(path) + up['GCC_LIST'] = [bname] + up['NAME'] = bname.split('.')[0] + if not path: path = '.' + elif os.path.isdir(path): + try: + execfile('%s/uwsgiplugin.py' % path, up) + except: + f = open('%s/uwsgiplugin.py' % path) + exec(f.read(), up) + f.close() + else: + print("Error: unable to find directory '%s'" % path) + sys.exit(1) + + requires = [] + + p_cflags = cflags[:] + p_ldflags = ldflags[:] + + try: + p_cflags += up['CFLAGS'] + except: + pass + + try: + p_ldflags += up['LDFLAGS'] + except: + pass + + try: + p_libs = up['LIBS'] + except: + p_libs = [] + + post_build = None + + try: + requires = up['REQUIRES'] + except: + pass + + try: + post_build = up['post_build'] + except: + pass + + p_cflags.insert(0, '-I.') + + if name is None: + name = up['NAME'] + else: + p_cflags.append("-D%s_plugin=%s_plugin" % (up['NAME'], name)) + + try: + for opt in uc.config.options(name): + p_cflags.append('-DUWSGI_PLUGIN_%s_%s="%s"' % (name.upper(), opt.upper(), uc.config.get(name, opt, '1'))) + except: + pass + + if uc: + plugin_dest = uc.get('plugin_build_dir', uc.get('plugin_dir')) + '/' + name + '_plugin' + else: + plugin_dest = name + '_plugin' + + shared_flag = '-shared' + + gcc_list = [] + + if uwsgi_os == 'Darwin': + shared_flag = '-dynamiclib -undefined dynamic_lookup' + + for cfile in up['GCC_LIST']: + if cfile.endswith('.a'): + gcc_list.append(cfile) + elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m') and not cfile.endswith('.go') and not cfile.endswith('.o'): + gcc_list.append(path + '/' + cfile + '.c') + else: + if cfile.endswith('.go'): + p_cflags.append('-Wno-error') + gcc_list.append(path + '/' + cfile) + for bfile in up.get('BINARY_LIST', []): + try: + binary_link_cmd = "ld -r -b binary -o %s/%s.o %s/%s" % (path, bfile[1], path, bfile[1]) + print(binary_link_cmd) + if os.system(binary_link_cmd) != 0: + raise Exception('unable to link binary file') + for kind in ('start','end'): + objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=%s_%s %s/%s.o" % (binarize('%s/%s' % (path, bfile[1])), kind, bfile[0], kind, path, bfile[1]) + print(objcopy_cmd) + if os.system(objcopy_cmd) != 0: + raise Exception('unable to link binary file') + gcc_list.append('%s/%s.o' % (path, bfile[1])) + except: + pass + + try: + p_ldflags.remove('-Wl,--no-undefined') + except: + pass + + try: + p_cflags.remove('-Wwrite-strings') + except: + pass + + try: + p_cflags.remove('-Werror=write-strings') + except: + pass + + try: + p_cflags.remove('-Wdeclaration-after-statement') + except: + pass + + try: + p_cflags.remove('-Werror=declaration-after-statement') + except: + pass + + try: + p_cflags.remove('-Winline') + except: + pass + + try: + p_cflags.remove('-pie') + except: + pass + + if GCC in ('clang',): + try: + p_cflags.remove('-fno-fast-math') + p_cflags.remove('-ggdb3') + except: + pass + + if uwsgi_os.startswith('CYGWIN'): + try: + p_cflags.remove('-fstack-protector') + p_ldflags.remove('-fstack-protector') + except: + pass + + need_pic = ' -fPIC' + # on cygwin we do not need PIC + if uwsgi_os.startswith('CYGWIN'): + need_pic = ' -L. -luwsgi' + + gccline = "%s%s %s -o %s.so %s %s %s %s" % (GCC, need_pic, shared_flag, plugin_dest, ' '.join(uniq_warnings(p_cflags)), ' '.join(gcc_list), ' '.join(uniq_warnings(p_ldflags)), ' '.join(uniq_warnings(p_libs)) ) + print_compilation_output("[%s] %s.so" % (GCC, plugin_dest), gccline) + + ret = os.system(gccline) + if ret != 0: + print("*** unable to build %s plugin ***" % name) + sys.exit(1) + + try: + if requires: + f = open('.uwsgi_plugin_section', 'w') + for rp in requires: + f.write("requires=%s\n" % rp) + f.close() + objline = "objcopy %s.so --add-section uwsgi=.uwsgi_plugin_section %s.so" % (plugin_dest, plugin_dest) + print_compilation_output(None, objline) + os.system(objline) + os.unlink('.uwsgi_plugin_section') + except: + pass + + if post_build: + post_build(uc) + + print("build time: %d seconds" % (time.time() - plugin_started_at)) + print("*** %s plugin built and available in %s ***" % (name, plugin_dest + '.so')) + +def vararg_callback(option, opt_str, value, parser): + assert value is None + value = [] + for arg in parser.rargs: + # stop on --foo like options + if arg[:2] == "--" and len(arg) > 2: + break + # stop on -a, but not on -3 or -3.0 + if arg[:1] == "-" and len(arg) > 1: + break + value.append(arg) + + del parser.rargs[:len(value)] + setattr(parser.values, option.dest, value) + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option("-b", "--build", action="callback", callback=vararg_callback, dest="build", help="build a specific profile if provided or default.ini", metavar="PROFILE") + parser.add_option("-f", "--cflags", action="callback", callback=vararg_callback, dest="cflags", help="same as --build but less verbose", metavar="PROFILE") + parser.add_option("-u", "--unbit", action="store_true", dest="unbit", help="build unbit profile") + parser.add_option("-p", "--plugin", action="callback", callback=vararg_callback, dest="plugin", help="build a plugin as shared library, optionally takes a build profile name", metavar="PLUGIN [PROFILE]") + parser.add_option("-x", "--extra-plugin", action="callback", callback=vararg_callback, dest="extra_plugin", help="build an external plugin as shared library, takes an optional include dir", metavar="PLUGIN [NAME]") + parser.add_option("-c", "--clean", action="store_true", dest="clean", help="clean the build") + parser.add_option("-e", "--check", action="store_true", dest="check", help="run cppcheck") + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="more verbose build") + parser.add_option("-g", "--debug", action="store_true", dest="debug", help="build with debug symbols, affects only full build") + parser.add_option("-a", "--asan", action="store_true", dest="asan", help="build with address sanitizer, it's a debug option and affects only full build") + + (options, args) = parser.parse_args() + + if options.verbose: + verbose_build = True + + add_cflags = [] + add_ldflags = [] + + if options.debug: + add_cflags.append('-g') + add_ldflags.append('-g') + + if options.asan: + add_cflags.extend(['-g', '-fsanitize=address', '-fno-omit-frame-pointer']) + add_ldflags.extend(['-g', '-fsanitize=address']) + + if options.build is not None or options.cflags is not None: + is_cflags = options.cflags is not None + try: + if not is_cflags: + bconf = options.build[0] + else: + bconf = options.cflags[0] + except: + bconf = os.environ.get('UWSGI_PROFILE','default.ini') + if not bconf.endswith('.ini'): + bconf += '.ini' + if not '/' in bconf: + bconf = 'buildconf/%s' % bconf + + uc = uConf(bconf, is_cflags) + if add_cflags or add_ldflags: + gcc_list, cflags, ldflags, libs = uc.get_gcll() + if add_cflags: + cflags.extend(add_cflags) + if add_ldflags: + ldflags.extend(add_ldflags) + gcll = (gcc_list, cflags, ldflags, libs) + else: + gcll = None + build_uwsgi(uc, is_cflags, gcll=gcll) + elif options.unbit: + build_uwsgi(uConf('buildconf/unbit.ini')) + elif options.plugin: + try: + bconf = options.plugin[1] + except: + bconf = os.environ.get('UWSGI_PROFILE','default.ini') + if not bconf.endswith('.ini'): + bconf += '.ini' + if not '/' in bconf: + bconf = 'buildconf/%s' % bconf + uc = uConf(bconf) + gcc_list, cflags, ldflags, libs = uc.get_gcll() + try: + name = options.plugin[2] + except: + name = None + print("*** uWSGI building and linking plugin %s ***" % options.plugin[0] ) + build_plugin(options.plugin[0], uc, cflags, ldflags, libs, name) + elif options.extra_plugin: + print("*** uWSGI building and linking plugin from %s ***" % options.extra_plugin[0]) + cflags = os.environ['UWSGI_PLUGINS_BUILDER_CFLAGS'].split() + os.environ.get("CFLAGS", "").split() + cflags.append('-I.uwsgi_plugins_builder/') + ldflags = os.environ.get("LDFLAGS", "").split() + name = None + try: + name = options.extra_plugin[1] + except: + pass + build_plugin(options.extra_plugin[0], None, cflags, ldflags, None, name) + elif options.clean: + os.system("rm -f core/*.o") + os.system("rm -f proto/*.o") + os.system("rm -f lib/*.o") + os.system("rm -f plugins/*/*.o") + os.system("rm -f build/*.o") + os.system("rm -f core/dot_h.c") + os.system("rm -f core/config_py.c") + elif options.check: + os.system("cppcheck --max-configs=1000 --enable=all -q core/ plugins/ proto/ lib/ apache2/") + else: + parser.print_help() + sys.exit(1) diff --git a/ihatemoney/static/css/datatables.min.css b/ihatemoney/static/css/datatables.min.css new file mode 100644 index 00000000..a4e03a77 --- /dev/null +++ b/ihatemoney/static/css/datatables.min.css @@ -0,0 +1,15 @@ +/* + * This combined file was created by the DataTables downloader builder: + * https://datatables.net/download + * + * To rebuild or modify this file with the latest versions of the included + * software please visit: + * https://datatables.net/download/#dt/dt-1.10.20 + * + * Included libraries: + * DataTables 1.10.20 + */ + +table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead th,table.dataTable thead td{padding:10px 18px;border-bottom:1px solid #111}table.dataTable thead th:active,table.dataTable thead td:active{outline:none}table.dataTable tfoot th,table.dataTable tfoot td{padding:10px 18px 6px 18px;border-top:1px solid #111}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;*cursor:hand;background-repeat:no-repeat;background-position:center right}table.dataTable thead .sorting{background-image:url("../images/sort_both.png")}table.dataTable thead .sorting_asc{background-image:url("../images/sort_asc.png")}table.dataTable thead .sorting_desc{background-image:url("../images/sort_desc.png")}table.dataTable thead .sorting_asc_disabled{background-image:url("../images/sort_asc_disabled.png")}table.dataTable thead .sorting_desc_disabled{background-image:url("../images/sort_desc_disabled.png")}table.dataTable tbody tr{background-color:#ffffff}table.dataTable tbody tr.selected{background-color:#B0BED9}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border tbody th,table.dataTable.row-border tbody td,table.dataTable.display tbody th,table.dataTable.display tbody td{border-top:1px solid #ddd}table.dataTable.row-border tbody tr:first-child th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display tbody tr:first-child th,table.dataTable.display tbody tr:first-child td{border-top:none}table.dataTable.cell-border tbody th,table.dataTable.cell-border tbody td{border-top:1px solid #ddd;border-right:1px solid #ddd}table.dataTable.cell-border tbody tr th:first-child,table.dataTable.cell-border tbody tr td:first-child{border-left:1px solid #ddd}table.dataTable.cell-border tbody tr:first-child th,table.dataTable.cell-border tbody tr:first-child td{border-top:none}table.dataTable.stripe tbody tr.odd,table.dataTable.display tbody tr.odd{background-color:#f9f9f9}table.dataTable.stripe tbody tr.odd.selected,table.dataTable.display tbody tr.odd.selected{background-color:#acbad4}table.dataTable.hover tbody tr:hover,table.dataTable.display tbody tr:hover{background-color:#f6f6f6}table.dataTable.hover tbody tr:hover.selected,table.dataTable.display tbody tr:hover.selected{background-color:#aab7d1}table.dataTable.order-column tbody tr>.sorting_1,table.dataTable.order-column tbody tr>.sorting_2,table.dataTable.order-column tbody tr>.sorting_3,table.dataTable.display tbody tr>.sorting_1,table.dataTable.display tbody tr>.sorting_2,table.dataTable.display tbody tr>.sorting_3{background-color:#fafafa}table.dataTable.order-column tbody tr.selected>.sorting_1,table.dataTable.order-column tbody tr.selected>.sorting_2,table.dataTable.order-column tbody tr.selected>.sorting_3,table.dataTable.display tbody tr.selected>.sorting_1,table.dataTable.display tbody tr.selected>.sorting_2,table.dataTable.display tbody tr.selected>.sorting_3{background-color:#acbad5}table.dataTable.display tbody tr.odd>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd>.sorting_1{background-color:#f1f1f1}table.dataTable.display tbody tr.odd>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd>.sorting_2{background-color:#f3f3f3}table.dataTable.display tbody tr.odd>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd>.sorting_3{background-color:whitesmoke}table.dataTable.display tbody tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.dataTable.display tbody tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.dataTable.display tbody tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.dataTable.display tbody tr.even>.sorting_1,table.dataTable.order-column.stripe tbody tr.even>.sorting_1{background-color:#fafafa}table.dataTable.display tbody tr.even>.sorting_2,table.dataTable.order-column.stripe tbody tr.even>.sorting_2{background-color:#fcfcfc}table.dataTable.display tbody tr.even>.sorting_3,table.dataTable.order-column.stripe tbody tr.even>.sorting_3{background-color:#fefefe}table.dataTable.display tbody tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_1{background-color:#acbad5}table.dataTable.display tbody tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_2{background-color:#aebcd6}table.dataTable.display tbody tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{background-color:#eaeaea}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{background-color:#ececec}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{background-color:#efefef}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{background-color:#a2aec7}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{background-color:#a3b0c9}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{background-color:#a5b2cb}table.dataTable.no-footer{border-bottom:1px solid #111}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable.compact thead th,table.dataTable.compact thead td{padding:4px 17px 4px 4px}table.dataTable.compact tfoot th,table.dataTable.compact tfoot td{padding:4px}table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable,table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both;*zoom:1;zoom:1}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{margin-left:0.5em}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:0.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:0.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:0.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;*cursor:hand;color:#333 !important;border:1px solid transparent;border-radius:2px}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:#333 !important;border:1px solid #979797;background-color:white;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(100%, #dcdcdc));background:-webkit-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-moz-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-ms-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-o-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:linear-gradient(to bottom, #fff 0%, #dcdcdc 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:40px;margin-left:-50%;margin-top:-25px;padding-top:20px;text-align:center;font-size:1.2em;background-color:white;background:-webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0)));background:-webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%)}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:#333}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid #111}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:0.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:0.5em}} + + diff --git a/ihatemoney/static/images/sort_asc.png b/ihatemoney/static/images/sort_asc.png new file mode 100644 index 0000000000000000000000000000000000000000..e1ba61a8055fcb18273f2468d335572204667b1f GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3I*bWaz@5R22v2@;zYta_*?F5u6Q zWR@in#&u+WgT?Hi<}D3B3}GOXuX|8Oj3tosHiJ3*4TN zC7>_x-r1O=t(?KoTC+`+>7&2GzdqLHBg&F)2Q?&EGZ+}|Rpsc~9`m>jw35No)z4*} HQ$iB}HK{Sd literal 0 HcmV?d00001 diff --git a/ihatemoney/static/images/sort_asc_disabled.png b/ihatemoney/static/images/sort_asc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..fb11dfe24a6c564cb7ddf8bc96703ebb121df1e7 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S0wixl{&NRX(Vi}jAsXkC6BcOhI9!^3NY?Do zDX;f`c1`y6n0RgO@$!H7chZT&|Jn0dmaqO^XNm-CGtk!Ur<_=Jws3;%W$<+Mb6Mw<&;$T1GdZXL literal 0 HcmV?d00001 diff --git a/ihatemoney/static/images/sort_both.png b/ihatemoney/static/images/sort_both.png new file mode 100644 index 0000000000000000000000000000000000000000..af5bc7c5a10b9d6d57cb641aeec752428a07f0ca GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S0wixl{&NRX6FglULp08Bycxyy87-Q;~nRxO8@-UU*I^KVWyN+&SiMHu5xDOu|HNvwzODfTdXjhVyNu1 z#7^XbGKZ7LW3XeONb$RKLeE*WhqbYpIXPIqK@r4)v+qN8um%99%MPpS9d#7Ed7SL@Bp00i_>zopr0H-Zb Aj{pDw literal 0 HcmV?d00001 diff --git a/ihatemoney/static/images/sort_desc.png b/ihatemoney/static/images/sort_desc.png new file mode 100644 index 0000000000000000000000000000000000000000..0e156deb5f61d18f9e2ec5da4f6a8c94a5b4fb41 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3I*R8JSj5R22v2@yo z(czD9$NuDl3Ljm9c#_#4$vXUz=f1~&WY3aa=h!;z7fOEN>ySP9QA=6C-^Dmb&tuM= z4Z&=WZU;2WF>e%GI&mWJk^K!jrbro{W;-I>FeCfLGJl3}+Z^2)3Kw?+EoAU?^>bP0 Hl+XkKC^j|Q{b@g3TV7E(Grjn^aLC2o)_ptHrtUEoT$S@q)~)7U@V;W{6)!%@ u>N?4t-1qslpJw9!O?PJ&w0Cby").css({position:"fixed",top:0,left:-1*f(z).scrollLeft(),height:1,width:1, +overflow:"hidden"}).append(f("
").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(f("
").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}f.extend(a.oBrowser,q.__browser);a.oScroll.iBarWidth=q.__browser.barWidth} +function mb(a,b,c,d,e,h){var g=!1;if(c!==p){var k=c;g=!0}for(;d!==e;)a.hasOwnProperty(d)&&(k=g?b(k,a[d],d,a):a[d],g=!0,d+=h);return k}function Ia(a,b){var c=q.defaults.column,d=a.aoColumns.length;c=f.extend({},q.models.oColumn,c,{nTh:b?b:y.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=f.extend({},q.models.oSearch,c[d]);ma(a,d,f(b).data())}function ma(a,b,c){b=a.aoColumns[b]; +var d=a.oClasses,e=f(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var h=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);h&&(b.sWidthOrig=h[1])}c!==p&&null!==c&&(kb(c),L(q.defaults.column,c,!0),c.mDataProp===p||c.mData||(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),f.extend(b,c),M(b,c,"sWidth","sWidthOrig"),c.iDataSort!==p&&(b.aDataSort=[c.iDataSort]),M(b,c,"aDataSort"));var g=b.mData,k=U(g), +l=b.mRender?U(b.mRender):null;c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=f.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=k(a,b,p,c);return l&&b?l(d,b,a,c):d};b.fnSetData=function(a,b,c){return Q(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==f.inArray("asc",b.asSorting);c=-1!==f.inArray("desc",b.asSorting);b.bSortable&&(a||c)?a&&!c?(b.sSortingClass= +d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI):(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI="")}function aa(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ja(a);for(var c=0,d=b.length;cn[m])d(k.length+ +n[m],l);else if("string"===typeof n[m]){var w=0;for(g=k.length;wb&&a[e]--; -1!=d&&c===p&&a.splice(d,1)}function ea(a,b,c,d){var e=a.aoData[b],h,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=I(a,b,d,"display")};if("dom"!==c&&(c&&"auto"!==c||"dom"!==e.src)){var k=e.anCells;if(k)if(d!==p)g(k[d],d);else for(c=0,h=k.length;c").appendTo(d));var l=0;for(b=k.length;ltr").attr("role","row");f(d).find(">tr>th, >tr>td").addClass(g.sHeaderTH);f(e).find(">tr>th, >tr>td").addClass(g.sFooterTH);if(null!==e)for(a=a.aoFooter[0],l=0,b=a.length;l=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);g=a._iDisplayStart;var n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,K(a,!1);else if(!k)a.iDraw++;else if(!a.bDestroying&&!qb(a))return;if(0!==l.length)for(h=k?a.aoData.length:n,k=k?0:g;k",{"class":e?d[0]:""}).append(f("",{valign:"top",colSpan:W(a),"class":a.oClasses.sRowEmpty}).html(c))[0];A(a,"aoHeaderCallback","header",[f(a.nTHead).children("tr")[0], +Oa(a),g,n,l]);A(a,"aoFooterCallback","footer",[f(a.nTFoot).children("tr")[0],Oa(a),g,n,l]);d=f(a.nTBody);d.children().detach();d.append(f(b));A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function V(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&rb(a);d?ia(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;S(a);a._drawHold=!1}function sb(a){var b=a.oClasses,c=f(a.nTable);c=f("
").insertBefore(c);var d=a.oFeatures,e= +f("
",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var h=a.sDom.split(""),g,k,l,n,m,p,u=0;u")[0];n=h[u+1];if("'"==n||'"'==n){m="";for(p=2;h[u+p]!=n;)m+=h[u+p],p++;"H"==m?m=b.sJUIHeader:"F"==m&&(m=b.sJUIFooter);-1!=m.indexOf(".")?(n=m.split("."),l.id=n[0].substr(1,n[0].length-1),l.className=n[1]):"#"==m.charAt(0)?l.id=m.substr(1, +m.length-1):l.className=m;u+=p}e.append(l);e=f(l)}else if(">"==k)e=e.parent();else if("l"==k&&d.bPaginate&&d.bLengthChange)g=tb(a);else if("f"==k&&d.bFilter)g=ub(a);else if("r"==k&&d.bProcessing)g=vb(a);else if("t"==k)g=wb(a);else if("i"==k&&d.bInfo)g=xb(a);else if("p"==k&&d.bPaginate)g=yb(a);else if(0!==q.ext.feature.length)for(l=q.ext.feature,p=0,n=l.length;p',k=d.sSearch;k=k.match(/_INPUT_/)?k.replace("_INPUT_",g):k+g;b=f("
",{id:h.f?null:c+"_filter","class":b.sFilter}).append(f("
").addClass(b.sLength);a.aanFeatures.l||(l[0].id=c+"_length");l.children().append(a.oLanguage.sLengthMenu.replace("_MENU_", +e[0].outerHTML));f("select",l).val(a._iDisplayLength).on("change.DT",function(b){Va(a,f(this).val());S(a)});f(a.nTable).on("length.dt.DT",function(b,c,d){a===c&&f("select",l).val(d)});return l[0]}function yb(a){var b=a.sPaginationType,c=q.ext.pager[b],d="function"===typeof c,e=function(a){S(a)};b=f("
").addClass(a.oClasses.sPaging+b)[0];var h=a.aanFeatures;d||c.fnInit(a,b,e);h.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,g=a._iDisplayLength, +f=a.fnRecordsDisplay(),m=-1===g;b=m?0:Math.ceil(b/g);g=m?1:Math.ceil(f/g);f=c(b,g);var p;m=0;for(p=h.p.length;mh&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e",{id:a.aanFeatures.r?null:a.sTableId+"_processing","class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function K(a,b){a.oFeatures.bProcessing&&f(a.aanFeatures.r).css("display",b?"block":"none");A(a,null,"processing",[a,b])}function wb(a){var b=f(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY, +h=a.oClasses,g=b.children("caption"),k=g.length?g[0]._captionSide:null,l=f(b[0].cloneNode(!1)),n=f(b[0].cloneNode(!1)),m=b.children("tfoot");m.length||(m=null);l=f("
",{"class":h.sScrollWrapper}).append(f("
",{"class":h.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?d?B(d):null:"100%"}).append(f("
",{"class":h.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(l.removeAttr("id").css("margin-left",0).append("top"===k?g:null).append(b.children("thead"))))).append(f("
", +{"class":h.sScrollBody}).css({position:"relative",overflow:"auto",width:d?B(d):null}).append(b));m&&l.append(f("
",{"class":h.sScrollFoot}).css({overflow:"hidden",border:0,width:d?d?B(d):null:"100%"}).append(f("
",{"class":h.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",0).append("bottom"===k?g:null).append(b.children("tfoot")))));b=l.children();var p=b[0];h=b[1];var u=m?b[2]:null;if(d)f(h).on("scroll.DT",function(a){a=this.scrollLeft;p.scrollLeft=a;m&&(u.scrollLeft=a)}); +f(h).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=p;a.nScrollBody=h;a.nScrollFoot=u;a.aoDrawCallback.push({fn:na,sName:"scrolling"});return l[0]}function na(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY;b=b.iBarWidth;var h=f(a.nScrollHead),g=h[0].style,k=h.children("div"),l=k[0].style,n=k.children("table");k=a.nScrollBody;var m=f(k),w=k.style,u=f(a.nScrollFoot).children("div"),q=u.children("table"),t=f(a.nTHead),r=f(a.nTable),v=r[0],za=v.style,T=a.nTFoot?f(a.nTFoot):null,A=a.oBrowser, +x=A.bScrollOversize,ac=J(a.aoColumns,"nTh"),Ya=[],y=[],z=[],C=[],G,H=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};var D=k.scrollHeight>k.clientHeight;if(a.scrollBarVis!==D&&a.scrollBarVis!==p)a.scrollBarVis=D,aa(a);else{a.scrollBarVis=D;r.children("thead, tfoot").remove();if(T){var E=T.clone().prependTo(r);var F=T.find("tr");E=E.find("tr")}var I=t.clone().prependTo(r);t=t.find("tr");D=I.find("tr");I.find("th, td").removeAttr("tabindex"); +c||(w.width="100%",h[0].style.width="100%");f.each(ua(a,I),function(b,c){G=ba(a,b);c.style.width=a.aoColumns[G].sWidth});T&&N(function(a){a.style.width=""},E);h=r.outerWidth();""===c?(za.width="100%",x&&(r.find("tbody").height()>k.offsetHeight||"scroll"==m.css("overflow-y"))&&(za.width=B(r.outerWidth()-b)),h=r.outerWidth()):""!==d&&(za.width=B(d),h=r.outerWidth());N(H,D);N(function(a){z.push(a.innerHTML);Ya.push(B(f(a).css("width")))},D);N(function(a,b){-1!==f.inArray(a,ac)&&(a.style.width=Ya[b])}, +t);f(D).height(0);T&&(N(H,E),N(function(a){C.push(a.innerHTML);y.push(B(f(a).css("width")))},E),N(function(a,b){a.style.width=y[b]},F),f(E).height(0));N(function(a,b){a.innerHTML='
'+z[b]+"
";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=Ya[b]},D);T&&N(function(a,b){a.innerHTML='
'+C[b]+"
";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=y[b]},E);r.outerWidth()< +h?(F=k.scrollHeight>k.offsetHeight||"scroll"==m.css("overflow-y")?h+b:h,x&&(k.scrollHeight>k.offsetHeight||"scroll"==m.css("overflow-y"))&&(za.width=B(F-b)),""!==c&&""===d||O(a,1,"Possible column misalignment",6)):F="100%";w.width=B(F);g.width=B(F);T&&(a.nScrollFoot.style.width=B(F));!e&&x&&(w.height=B(v.offsetHeight+b));c=r.outerWidth();n[0].style.width=B(c);l.width=B(c);d=r.height()>k.clientHeight||"scroll"==m.css("overflow-y");e="padding"+(A.bScrollbarLeft?"Left":"Right");l[e]=d?b+"px":"0px";T&& +(q[0].style.width=B(c),u[0].style.width=B(c),u[0].style[e]=d?b+"px":"0px");r.children("colgroup").insertBefore(r.children("thead"));m.trigger("scroll");!a.bSorted&&!a.bFiltered||a._drawHold||(k.scrollTop=0)}}function N(a,b,c){for(var d=0,e=0,h=b.length,g,k;e").appendTo(k.find("tbody"));k.find("thead, tfoot").remove(); +k.append(f(a.nTHead).clone()).append(f(a.nTFoot).clone());k.find("tfoot th, tfoot td").css("width","");n=ua(a,k.find("thead")[0]);for(q=0;q").css({width:r.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(q=0;q").css(h|| +e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(k).appendTo(p);h&&g?k.width(g):h?(k.css("width","auto"),k.removeAttr("width"),k.width()").css("width",B(a)).appendTo(b||y.body);b=a[0].offsetWidth;a.remove();return b}function Kb(a,b){var c=Lb(a,b);if(0>c)return null;var d=a.aoData[c];return d.nTr?d.anCells[b]:f("").html(I(a,c,b,"display"))[0]}function Lb(a,b){for(var c,d=-1,e=-1,h=0,g=a.aoData.length;hd&&(d=c.length,e=h);return e} +function B(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Y(a){var b=[],c=a.aoColumns;var d=a.aaSortingFixed;var e=f.isPlainObject(d);var h=[];var g=function(a){a.length&&!f.isArray(a[0])?h.push(a):f.merge(h,a)};f.isArray(d)&&g(d);e&&d.pre&&g(d.pre);g(a.aaSorting);e&&d.post&&g(d.post);for(a=0;an?1:0; +if(0!==m)return"asc"===l.dir?m:-m}m=c[a];n=c[b];return mn?1:0}):g.sort(function(a,b){var h,g=k.length,f=e[a]._aSortData,l=e[b]._aSortData;for(h=0;hp?1:0})}a.bSorted=!0}function Nb(a){var b=a.aoColumns,c=Y(a);a=a.oLanguage.oAria;for(var d=0,e=b.length;d/g,"");var f=h.nTh;f.removeAttribute("aria-sort"); +h.bSortable&&(0e?e+1:3))}e=0;for(h=d.length;ee?e+1:3))}a.aLastSort=d}function Mb(a,b){var c=a.aoColumns[b],d=q.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ca(a,b)));for(var h,g=q.ext.type.order[c.sType+"-pre"],k=0,f=a.aoData.length;k=h.length?[0,c[1]]:c)}));b.search!==p&&f.extend(a.oPreviousSearch, +Gb(b.search));if(b.columns)for(d=0,e=b.columns.length;d=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Ra(a,b){a=a.renderer;var c=q.ext.renderer[b];return f.isPlainObject(a)&&a[b]?c[a[b]]||c._:"string"===typeof a?c[a]||c._:c._}function D(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ka(a,b){var c=Pb.numbers_length,d=Math.floor(c/2);b<=c?a=Z(0,b):a<=d?(a=Z(0,c-2),a.push("ellipsis"),a.push(b-1)):(a>=b-1-d?a=Z(b-(c-2),b):(a=Z(a-d+2,a+d-1),a.push("ellipsis"), +a.push(b-1)),a.splice(0,0,"ellipsis"),a.splice(0,0,0));a.DT_el="span";return a}function Ha(a){f.each({num:function(b){return Da(b,a)},"num-fmt":function(b){return Da(b,a,bb)},"html-num":function(b){return Da(b,a,Ea)},"html-num-fmt":function(b){return Da(b,a,Ea,bb)}},function(b,c){C.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(C.type.search[b+a]=C.type.search.html)})}function Qb(a){return function(){var b=[Ca(this[q.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return q.ext.internal[a].apply(this, +b)}}var q=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new v(Ca(this[C.iApiIndex])):new v(this)};this.fnAddData=function(a,b){var c=this.api(!0);a=f.isArray(a)&&(f.isArray(a[0])||f.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===p||b)&&c.draw();return a.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===p||a?b.draw(!1): +(""!==d.sX||""!==d.sY)&&na(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===p||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0);a=d.rows(a);var e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===p||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,f){e=this.api(!0);null===b||b===p? +e.search(a,c,d,f):e.column(b).search(a,c,d,f);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==p){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==p||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==p?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(), +[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){a=this.api(!0).page(a);(b===p||b)&&a.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===p||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return Ca(this[C.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener= +function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===p||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===p||e)&&h.columns.adjust();(d===p||d)&&h.draw();return 0};this.fnVersionCheck=C.fnVersionCheck;var b=this,c=a===p,d=this.length;c&&(a={});this.oApi=this.internal=C.internal;for(var e in q.ext.internal)e&&(this[e]=Qb(e));this.each(function(){var e={},g=1").appendTo(w));r.nTHead=b[0];b=w.children("tbody");0===b.length&&(b=f("").appendTo(w));r.nTBody=b[0];b=w.children("tfoot");0===b.length&&0").appendTo(w));0===b.length||0===b.children().length?w.addClass(x.sNoFooter):0/g,cc=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,dc=/(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^|\-)/g,bb=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,P=function(a){return a&&!0!==a&&"-"!==a?!1: +!0},Sb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Tb=function(a,b){cb[b]||(cb[b]=new RegExp(Ua(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(cb[b],"."):a},db=function(a,b,c){var d="string"===typeof a;if(P(a))return!0;b&&d&&(a=Tb(a,b));c&&d&&(a=a.replace(bb,""));return!isNaN(parseFloat(a))&&isFinite(a)},Ub=function(a,b,c){return P(a)?!0:P(a)||"string"===typeof a?db(a.replace(Ea,""),b,c)?!0:null:null},J=function(a,b,c){var d=[],e=0,h=a.length;if(c!== +p)for(;ea.length)){var b=a.slice().sort();for(var c=b[0],d=1, +e=b.length;d")[0],$b=ya.textContent!==p,bc=/<.*?>/g,Sa=q.util.throttle,Wb=[],G=Array.prototype,ec=function(a){var b,c=q.settings,d=f.map(c,function(a,b){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase()){var e=f.inArray(a,d);return-1!==e?[c[e]]:null}if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?b=f(a):a instanceof f&&(b=a)}else return[];if(b)return b.map(function(a){e=f.inArray(this, +d);return-1!==e?c[e]:null}).toArray()};var v=function(a,b){if(!(this instanceof v))return new v(a,b);var c=[],d=function(a){(a=ec(a))&&c.push.apply(c,a)};if(f.isArray(a))for(var e=0,h=a.length;ea?new v(b[a],this[a]):null},filter:function(a){var b=[];if(G.filter)b=G.filter.call(this,a,this);else for(var c=0,d=this.length;c").addClass(c),f("td",d).addClass(c).html(b)[0].colSpan=W(a),e.push(d[0]))};h(c,d);b._details&&b._details.detach();b._details=f(e);b._detailsShow&&b._details.insertAfter(b.nTr)},hb=function(a,b){var c=a.context;c.length&&(a=c[0].aoData[b!==p?b:a[0]])&&a._details&&(a._details.remove(),a._detailsShow=p,a._details=p)},Yb=function(a,b){var c=a.context;c.length&&a.length&&(a=c[0].aoData[a[0]],a._details&&((a._detailsShow=b)?a._details.insertAfter(a.nTr): +a._details.detach(),ic(c[0])))},ic=function(a){var b=new v(a),c=a.aoData;b.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0g){var m=f.map(d,function(a,b){return a.bVisible?b:null});return[m[m.length+g]]}return[ba(a,g)];case "name":return f.map(e,function(a,b){return a===n[1]?b:null});default:return[]}if(b.nodeName&&b._DT_CellIndex)return[b._DT_CellIndex.column];g=f(h).filter(b).map(function(){return f.inArray(this, +h)}).toArray();if(g.length||!b.nodeName)return g;g=f(b).closest("*[data-dt-column]");return g.length?[g.data("dt-column")]:[]},a,c)};t("columns()",function(a,b){a===p?a="":f.isPlainObject(a)&&(b=a,a="");b=fb(b);var c=this.iterator("table",function(c){return kc(c,a,b)},1);c.selector.cols=a;c.selector.opts=b;return c});x("columns().header()","column().header()",function(a,b){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});x("columns().footer()","column().footer()",function(a, +b){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});x("columns().data()","column().data()",function(){return this.iterator("column-rows",Zb,1)});x("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});x("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return la(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});x("columns().nodes()", +"column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return la(a.aoData,e,"anCells",b)},1)});x("columns().visible()","column().visible()",function(a,b){var c=this,d=this.iterator("column",function(b,c){if(a===p)return b.aoColumns[c].bVisible;var d=b.aoColumns,e=d[c],h=b.aoData,n;if(a!==p&&e.bVisible!==a){if(a){var m=f.inArray(!0,J(d,"bVisible"),c+1);d=0;for(n=h.length;dd;return!0};q.isDataTable=q.fnIsDataTable=function(a){var b=f(a).get(0),c=!1;if(a instanceof +q.Api)return!0;f.each(q.settings,function(a,e){a=e.nScrollHead?f("table",e.nScrollHead)[0]:null;var d=e.nScrollFoot?f("table",e.nScrollFoot)[0]:null;if(e.nTable===b||a===b||d===b)c=!0});return c};q.tables=q.fnTables=function(a){var b=!1;f.isPlainObject(a)&&(b=a.api,a=a.visible);var c=f.map(q.settings,function(b){if(!a||a&&f(b.nTable).is(":visible"))return b.nTable});return b?new v(c):c};q.camelToHungarian=L;t("$()",function(a,b){b=this.rows(b).nodes();b=f(b);return f([].concat(b.filter(a).toArray(), +b.find(a).toArray()))});f.each(["on","one","off"],function(a,b){t(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0]=f.map(a[0].split(/\s/),function(a){return a.match(/\.dt\b/)?a:a+".dt"}).join(" ");var d=f(this.tables().nodes());d[b].apply(d,a);return this})});t("clear()",function(){return this.iterator("table",function(a){qa(a)})});t("settings()",function(){return new v(this.context,this.context)});t("init()",function(){var a=this.context;return a.length?a[0].oInit:null});t("data()", +function(){return this.iterator("table",function(a){return J(a.aoData,"_aData")}).flatten()});t("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,h=b.nTBody,g=b.nTHead,k=b.nTFoot,l=f(e);h=f(h);var n=f(b.nTableWrapper),m=f.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);a||(new v(b)).columns().visible(!0);n.off(".DT").find(":not(tbody *)").off(".DT");f(z).off(".DT-"+b.sInstance); +e!=g.parentNode&&(l.children("thead").detach(),l.append(g));k&&e!=k.parentNode&&(l.children("tfoot").detach(),l.append(k));b.aaSorting=[];b.aaSortingFixed=[];Aa(b);f(m).removeClass(b.asStripeClasses.join(" "));f("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);h.children().detach();h.append(m);g=a?"remove":"detach";l[g]();n[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),l.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&& +h.children().each(function(a){f(this).addClass(b.asDestroyStripes[a%p])}));c=f.inArray(b,q.settings);-1!==c&&q.settings.splice(c,1)})});f.each(["column","row","cell"],function(a,b){t(b+"s().every()",function(a){var c=this.selector.opts,e=this;return this.iterator(b,function(d,f,k,l,n){a.call(e[b](f,"cell"===b?k:c,"cell"===b?c:p),f,k,l,n)})})});t("i18n()",function(a,b,c){var d=this.context[0];a=U(a)(d.oLanguage);a===p&&(a=b);c!==p&&f.isPlainObject(a)&&(a=a[c]!==p?a[c]:a._);return a.replace("%d",c)}); +q.version="1.10.20";q.settings=[];q.models={};q.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};q.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};q.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null, +sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};q.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1, +bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}}, +fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last", +sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:f.extend({},q.models.oSearch),sAjaxDataProp:"data", +sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};H(q.defaults);q.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};H(q.defaults.column);q.models.oSettings= +{oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{}, +aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0, +aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:p,oAjaxData:p,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==D(this)?1*this._iRecordsTotal: +this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==D(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};q.ext=C={buttons:{}, +classes:{},build:"dt/dt-1.10.20",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:q.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:q.version};f.extend(C,{afnFiltering:C.search,aTypes:C.type.detect,ofnSearch:C.type.search,oSort:C.type.order,afnSortData:C.order,aoFeatures:C.feature,oApi:C.internal,oStdClasses:C.classes,oPagination:C.pager}); +f.extend(q.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled", +sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"", +sJUIHeader:"",sJUIFooter:""});var Pb=q.ext.pager;f.extend(Pb,{simple:function(a,b){return["previous","next"]},full:function(a,b){return["first","previous","next","last"]},numbers:function(a,b){return[ka(a,b)]},simple_numbers:function(a,b){return["previous",ka(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ka(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ka(a,b),"last"]},_numbers:ka,numbers_length:7});f.extend(!0,q.ext.renderer,{pageButton:{_:function(a,b, +c,d,e,h){var g=a.oClasses,k=a.oLanguage.oPaginate,l=a.oLanguage.oAria.paginate||{},n,m,q=0,t=function(b,d){var p,r=g.sPageButtonDisabled,u=function(b){Xa(a,b.data.action,!0)};var w=0;for(p=d.length;w").appendTo(b);t(x,v)}else{n=null;m=v;x=a.iTabIndex;switch(v){case "ellipsis":b.append('');break;case "first":n=k.sFirst;0===e&&(x=-1,m+=" "+r);break;case "previous":n=k.sPrevious;0===e&&(x=-1,m+= +" "+r);break;case "next":n=k.sNext;e===h-1&&(x=-1,m+=" "+r);break;case "last":n=k.sLast;e===h-1&&(x=-1,m+=" "+r);break;default:n=v+1,m=e===v?g.sPageButtonActive:""}null!==n&&(x=f("",{"class":g.sPageButton+" "+m,"aria-controls":a.sTableId,"aria-label":l[v],"data-dt-idx":q,tabindex:x,id:0===c&&"string"===typeof v?a.sTableId+"_"+v:null}).html(n).appendTo(b),$a(x,{action:v},u),q++)}}};try{var v=f(b).find(y.activeElement).data("dt-idx")}catch(mc){}t(f(b).empty(),d);v!==p&&f(b).find("[data-dt-idx="+ +v+"]").focus()}}});f.extend(q.ext.type.detect,[function(a,b){b=b.oLanguage.sDecimal;return db(a,b)?"num"+b:null},function(a,b){if(a&&!(a instanceof Date)&&!cc.test(a))return null;b=Date.parse(a);return null!==b&&!isNaN(b)||P(a)?"date":null},function(a,b){b=b.oLanguage.sDecimal;return db(a,b,!0)?"num-fmt"+b:null},function(a,b){b=b.oLanguage.sDecimal;return Ub(a,b)?"html-num"+b:null},function(a,b){b=b.oLanguage.sDecimal;return Ub(a,b,!0)?"html-num-fmt"+b:null},function(a,b){return P(a)||"string"=== +typeof a&&-1!==a.indexOf("<")?"html":null}]);f.extend(q.ext.type.search,{html:function(a){return P(a)?a:"string"===typeof a?a.replace(Rb," ").replace(Ea,""):""},string:function(a){return P(a)?a:"string"===typeof a?a.replace(Rb," "):a}});var Da=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Tb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};f.extend(C.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return P(a)? +"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return P(a)?"":"string"===typeof a?a.toLowerCase():a.toString?a.toString():""},"string-asc":function(a,b){return ab?1:0},"string-desc":function(a,b){return ab?-1:0}});Ha("");f.extend(!0,q.ext.renderer,{header:{_:function(a,b,c,d){f(a.nTable).on("order.dt.DT",function(e,f,g,k){a===f&&(e=c.idx,b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass("asc"==k[e]?d.sSortAsc:"desc"==k[e]?d.sSortDesc: +c.sSortingClass))})},jqueryui:function(a,b,c,d){f("
").addClass(d.sSortJUIWrapper).append(b.contents()).append(f("").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);f(a.nTable).on("order.dt.DT",function(e,f,g,k){a===f&&(e=c.idx,b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass("asc"==k[e]?d.sSortAsc:"desc"==k[e]?d.sSortDesc:c.sSortingClass),b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass("asc"== +k[e]?d.sSortJUIAsc:"desc"==k[e]?d.sSortJUIDesc:c.sSortingClassJUI))})}}});var ib=function(a){return"string"===typeof a?a.replace(//g,">").replace(/"/g,"""):a};q.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return ib(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g, +a)+f+(e||"")}}},text:function(){return{display:ib,filter:ib}}};f.extend(q.ext.internal,{_fnExternApiFunc:Qb,_fnBuildAjax:va,_fnAjaxUpdate:qb,_fnAjaxParameters:zb,_fnAjaxUpdateDraw:Ab,_fnAjaxDataSrc:wa,_fnAddColumn:Ia,_fnColumnOptions:ma,_fnAdjustColumnSizing:aa,_fnVisibleToColumnIndex:ba,_fnColumnIndexToVisible:ca,_fnVisbleColumns:W,_fnGetColumns:oa,_fnColumnTypes:Ka,_fnApplyColumnDefs:nb,_fnHungarianMap:H,_fnCamelToHungarian:L,_fnLanguageCompat:Ga,_fnBrowserDetect:lb,_fnAddData:R,_fnAddTr:pa,_fnNodeToDataIndex:function(a, +b){return b._DT_RowIndex!==p?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return f.inArray(c,a.aoData[b].anCells)},_fnGetCellData:I,_fnSetCellData:ob,_fnSplitObjNotation:Na,_fnGetObjectDataFn:U,_fnSetObjectDataFn:Q,_fnGetDataMaster:Oa,_fnClearTable:qa,_fnDeleteIndex:ra,_fnInvalidate:ea,_fnGetRowElements:Ma,_fnCreateTr:La,_fnBuildHead:pb,_fnDrawHead:ha,_fnDraw:S,_fnReDraw:V,_fnAddOptionsHtml:sb,_fnDetectHeader:fa,_fnGetUniqueThs:ua,_fnFeatureHtmlFilter:ub,_fnFilterComplete:ia,_fnFilterCustom:Db, +_fnFilterColumn:Cb,_fnFilter:Bb,_fnFilterCreateSearch:Ta,_fnEscapeRegex:Ua,_fnFilterData:Eb,_fnFeatureHtmlInfo:xb,_fnUpdateInfo:Hb,_fnInfoMacros:Ib,_fnInitialise:ja,_fnInitComplete:xa,_fnLengthChange:Va,_fnFeatureHtmlLength:tb,_fnFeatureHtmlPaginate:yb,_fnPageChange:Xa,_fnFeatureHtmlProcessing:vb,_fnProcessingDisplay:K,_fnFeatureHtmlTable:wb,_fnScrollDraw:na,_fnApplyToChildren:N,_fnCalculateColumnWidths:Ja,_fnThrottle:Sa,_fnConvertToWidth:Jb,_fnGetWidestNode:Kb,_fnGetMaxLenString:Lb,_fnStringToCss:B, +_fnSortFlatten:Y,_fnSort:rb,_fnSortAria:Nb,_fnSortListener:Za,_fnSortAttachListener:Qa,_fnSortingClasses:Aa,_fnSortData:Mb,_fnSaveState:Ba,_fnLoadState:Ob,_fnSettingsFromNode:Ca,_fnLog:O,_fnMap:M,_fnBindAction:$a,_fnCallbackReg:E,_fnCallbackFire:A,_fnLengthOverflow:Wa,_fnRenderer:Ra,_fnDataSource:D,_fnRowAttributes:Pa,_fnExtend:ab,_fnCalculateEnd:function(){}});f.fn.dataTable=q;q.$=f;f.fn.dataTableSettings=q.settings;f.fn.dataTableExt=q.ext;f.fn.DataTable=function(a){return f(this).dataTable(a).api()}; +f.each(q,function(a,b){f.fn.DataTable[a]=b});return f.fn.dataTable}); + + diff --git a/ihatemoney/templates/dashboard.html b/ihatemoney/templates/dashboard.html index 807e3e2f..3d0365af 100644 --- a/ihatemoney/templates/dashboard.html +++ b/ihatemoney/templates/dashboard.html @@ -2,21 +2,32 @@ {% block content %} {% if is_admin_dashboard_activated %} - + + + + + + + + + + {% for project in projects|sort(attribute='name') %} - + + + {% if project.has_bills() %} - - + + {% else %} - - + + {% endif %} - + {% endfor %} @@ -24,4 +35,9 @@ {% else %}
{{ _("The Dashboard is currently deactivated.") }}
{% endif %} + {% endblock %} diff --git a/ihatemoney/templates/layout.html b/ihatemoney/templates/layout.html index 664182ae..41b12e52 100644 --- a/ihatemoney/templates/layout.html +++ b/ihatemoney/templates/layout.html @@ -6,12 +6,14 @@ + + {% block head %}{% endblock %}
{{ _("Project") }}{{ _("Number of members") }}{{ _("Number of bills") }}{{_("Newest bill")}}{{_("Oldest bill")}}{{_("Actions")}}
{{ _("Project") }}{{ _("Number of members") }}{{ _("Number of bills") }}{{_("Newest bill")}}{{_("Oldest bill")}}{{_("Actions")}}
{{ project.name }}{{ project.members | count }}{{ project.get_bills().count() }}{{ project.name }}{{ project.members | count }}{{ project.get_bills().count() }}{{ project.get_bills().all()[0].date }}{{ project.get_bills().all()[-1].date }}{{ project.get_bills().all()[0].date }}{{ project.get_bills().all()[-1].date }} + {{ _('edit') }} {{ _('delete') }} -