Skip to content
Browse files

Merge branch 'channel_history'

  • Loading branch information...
2 parents 67625c2 + ee660c1 commit e117997272788ddc1cafdd0ecb2560c08a42762a @Vagabond committed Dec 2, 2010
Showing with 380 additions and 12 deletions.
  1. +1 −1 Makefile
  2. +7 −0 bin/ape.conf
  3. +66 −3 modules/libape-spidermonkey.c
  4. +1 −0 modules/plugins.h
  5. +38 −1 src/channel.c
  6. +4 −0 src/channel.h
  7. +160 −0 src/channel_history.c
  8. +57 −0 src/channel_history.h
  9. +5 −0 src/config.h
  10. +1 −0 src/extend.h
  11. +25 −7 src/raw.c
  12. +1 −0 src/users.h
  13. +9 −0 src/utils.c
  14. +5 −0 src/utils.h
View
2 Makefile
@@ -4,7 +4,7 @@ prefix = /usr/local
bindir = $(prefix)/bin
-SRC=src/entry.c src/sock.c src/hash.c src/handle_http.c src/cmd.c src/users.c src/channel.c src/config.c src/json.c src/json_parser.c src/plugins.c src/http.c src/extend.c src/utils.c src/ticks.c src/base64.c src/pipe.c src/raw.c src/events.c src/event_kqueue.c src/event_epoll.c src/transports.c src/servers.c src/dns.c src/sha1.c src/log.c src/parser.c src/md5.c
+SRC=src/entry.c src/sock.c src/hash.c src/handle_http.c src/cmd.c src/users.c src/channel.c src/config.c src/json.c src/json_parser.c src/plugins.c src/http.c src/extend.c src/utils.c src/ticks.c src/base64.c src/pipe.c src/raw.c src/events.c src/event_kqueue.c src/event_epoll.c src/transports.c src/servers.c src/dns.c src/sha1.c src/log.c src/parser.c src/md5.c src/channel_history.c
CFLAGS = -Wall -O2 -minline-all-stringops -rdynamic -I ./deps/udns-0.0.9/
LFLAGS=-ldl -lm -lpthread
View
7 bin/ape.conf
@@ -32,6 +32,13 @@ Config {
modules_conf = ../modules/conf/
}
+Channels {
+ # default max size of history. 0 for no history.
+ #history_default_max_size = 10
+ # RAWs you want to be added to history (space is seperator). ALL or comment for all RAWs.
+ #history_default_raw_filter = DATA
+}
+
# Proxy section is used to resolve hostname and allow access to a IP:port (Middleware-TCPSocket feature)
#Proxy {
View
69 modules/libape-spidermonkey.c
@@ -572,6 +572,7 @@ APE_JS_NATIVE(apepipe_sm_set_property)
case CHANNEL_PIPE:
/* Set property on directly on the channel (not on the pipe) */
add_property(&((CHANNEL *)(pipe->pipe))->properties, key, valuextend, typextend, EXTEND_ISPUBLIC);
+ update_chan_history_size((CHANNEL *)(pipe->pipe));
break;
case CUSTOM_PIPE:
add_property(&pipe->properties, key, valuextend, typextend, EXTEND_ISPUBLIC);
@@ -756,6 +757,47 @@ APE_JS_NATIVE(apepipe_sm_send_response)
return sm_send_raw(cx, JS_GetPrivate(cx, JSVAL_TO_OBJECT(pipe)), JSVAL_TO_INT(chl), argc, argv, g_ape);
}
+APE_JS_NATIVE(apechannel_sm_ban)
+//{
+ char *ip, *reason;
+ unsigned int expire;
+ USERS *user;
+ JSObject *user_obj;
+ CHANNEL *chan = JS_GetPrivate(cx, obj);
+
+ if ( chan == NULL ||
+ !JSVAL_IS_OBJECT(argv[0]) ||
+ !JSVAL_IS_STRING(argv[1]) ||
+ !JSVAL_IS_STRING(argv[2]) ||
+ !JSVAL_IS_INT(argv[3]) ||
+ !JS_ConvertArguments(cx, 4, argv, "ossu", &user_obj, &ip, &reason, &expire) ||
+ !JS_InstanceOf(cx, user_obj, &user_class, 0) ||
+ (user = JS_GetPrivate(cx, user_obj)) == NULL ||
+ strlen(ip) < 3 /* min. ::1 (localhost) ipv6 */
+ ) {
+ *rval = JSVAL_FALSE;
+ }
+ else {
+ ban(chan, user, ip, reason, expire, g_ape);
+ *rval = JSVAL_TRUE;
+ }
+
+ return JS_TRUE;
+}
+
+APE_JS_NATIVE(apechannel_sm_get_flags)
+//{
+ CHANNEL *chan = JS_GetPrivate(cx, obj);
+
+ if (chan == NULL) {
+ return JS_TRUE;
+ }
+
+ *rval = INT_TO_JSVAL(getflags(chan));
+
+ return JS_TRUE;
+}
+
APE_JS_NATIVE(apechannel_sm_get_property)
//{
const char *property;
@@ -788,6 +830,23 @@ APE_JS_NATIVE(apechannel_sm_get_property)
return JS_TRUE;
}
+APE_JS_NATIVE(apechannel_sm_set_flags)
+//{
+ int flags;
+
+ CHANNEL *chan = JS_GetPrivate(cx, obj);
+
+ if ( chan == NULL ||
+ !JSVAL_IS_INT(argv[1]) ||
+ !JS_ConvertArguments(cx, 1, argv, "i", &flags)
+ ) {
+ return JS_TRUE;
+ }
+
+ setflags(chan, flags);
+ return JS_TRUE;
+}
+
APE_JS_NATIVE(apechannel_sm_set_property)
//{
char *key;
@@ -814,7 +873,8 @@ APE_JS_NATIVE(apechannel_sm_set_property)
add_property(&chan->properties, key, JS_GetStringBytes(property), EXTEND_STR, EXTEND_ISPUBLIC);
}
-
+ update_chan_history_size(chan);
+
return JS_TRUE;
}
@@ -1087,6 +1147,9 @@ static JSFunctionSpec apechannel_funcs[] = {
JS_FS("getProperty", apechannel_sm_get_property, 1, 0, 0),
JS_FS("setProperty", apechannel_sm_set_property, 2, 0, 0),
JS_FS("isInteractive", apechannel_sm_isinteractive, 1, 0, 0),
+ JS_FS("getFlags", apechannel_sm_get_flags, 0, 0, 0),
+ JS_FS("setFlags", apechannel_sm_set_flags, 1, 0, 0),
+ JS_FS("ban", apechannel_sm_ban, 4, 0, 0),
JS_FS_END
};
@@ -1792,7 +1855,7 @@ APE_JS_NATIVE(ape_sm_rmchan)
} else {
return JS_TRUE;
}
-
+
rmchan(chan, g_ape);
return JS_TRUE;
@@ -3103,7 +3166,7 @@ static void ape_cb_rmchan(CHANNEL *chan, acetables *g_ape)
JSContext *gcx = ASMC;
params[0] = OBJECT_TO_JSVAL(APECHAN_TO_JSOBJ(chan));
-
+
APE_JS_EVENT("rmchan", 1, params);
jsobj = get_property(chan->properties, "jsobj");
View
1 modules/plugins.h
@@ -28,6 +28,7 @@
#include "../src/main.h"
#include "../src/channel.h"
+#include "../src/channel_history.h"
#include "../src/cmd.h"
#include "../src/extend.h"
#include "../src/users.h"
View
39 src/channel.c
@@ -26,6 +26,7 @@
#include "json.h"
#include "raw.h"
#include "plugins.h"
+#include "channel_history.h"
unsigned int isvalidchan(char *name)
{
@@ -65,6 +66,8 @@ CHANNEL *mkchan(char *chan, int flags, acetables *g_ape)
new_chan->properties = NULL;
new_chan->flags = flags | (*new_chan->name == '*' ? CHANNEL_NONINTERACTIVE : 0);
+ new_chan->history = init_channel_history(new_chan, g_ape->srv);
+
//memcpy(new_chan->topic, topic, strlen(topic)+1);
new_chan->pipe = init_pipe(new_chan, CHANNEL_PIPE, g_ape);
@@ -124,6 +127,7 @@ void rmchan(CHANNEL *chan, acetables *g_ape)
destroy_pipe(chan->pipe, g_ape);
+ free_channel_history(chan->history);
free(chan);
chan = NULL;
}
@@ -196,7 +200,8 @@ void join(USERS *user, CHANNEL *chan, acetables *g_ape)
newraw = forge_raw(RAW_CHANNEL, jlist);
post_raw(newraw, user, g_ape);
-
+ post_channel_history(chan, user, g_ape);
+
#if 0
if (user->flags & FLG_AUTOOP) {
setlevel(NULL, user, chan, 3);
@@ -378,6 +383,38 @@ unsigned int setlevel(USERS *user_actif, USERS *user_passif, CHANNEL *chan, unsi
return 0;
}
+void setflags(CHANNEL *chan, int flags) {
+ chan->flags = flags;
+}
+
+int getflags(CHANNEL *chan) {
+ return chan->flags;
+}
+
+unsigned int setflags_cmd(USERS *user, CHANNEL *chan, int flags, acetables *g_ape) {
+ RAW *newraw;
+ userslist *list;
+ json_item *jlist;
+
+ list = getuchan(user, chan);
+
+ if (list == NULL || list->level < 3) {
+ send_error(user, "SETFLAGS_ERROR", "112", g_ape);
+ return 0;
+ }
+
+ setflags(chan, flags);
+
+ jlist = json_new_object();
+ json_set_property_objN(jlist, "user", 4, get_json_object_user(user));
+ json_set_property_objN(jlist, "pipe", 4, get_json_object_channel(chan));
+
+ newraw = forge_raw(RAW_SETFLAGS, jlist);
+ post_raw_channel(newraw, chan, g_ape);
+
+ return 1;
+}
+
/*unsigned int settopic(USERS *user, CHANNEL *chan, const char *topic, acetables *g_ape)
{
RAW *newraw;
View
4 src/channel.h
@@ -40,6 +40,7 @@ typedef struct CHANNEL
struct _transpipe *pipe;
struct userslist *head;
+ struct CHANNEL_HISTORY_DEQUE *history;
struct BANNED *banned;
@@ -86,5 +87,8 @@ unsigned int isvalidchan(char *name);
json_item *get_json_object_channel(CHANNEL *chan);
+void setflags(CHANNEL *chan, int flags);
+int getflags(CHANNEL *chan);
+
#endif
View
160 src/channel_history.c
@@ -0,0 +1,160 @@
+/*
+ Copyright (C) 2010 Philipp Fuehrer <pf@netzbeben.de>
+
+ This file is part of APE Server.
+ APE is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ APE is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with APE ; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* channel_history.c */
+
+#include "channel_history.h"
+#include "utils.h"
+
+
+int get_channel_max_history_size(CHANNEL *chan) {
+ char *hs = get_property_val((chan)->properties, "max_history_size");
+ return (hs != NULL) ? strtol(hs, NULL, 10) : 0;
+}
+
+
+void history_append_element(CHANNEL_HISTORY_DEQUE *deque, RAW *raw) {
+ CHANNEL_HISTORY_NODE *node = xmalloc(sizeof(*node));
+ node->value = raw;
+
+ ++deque->length;
+
+ if (deque->head != NULL) {
+ node->next = deque->head;
+ deque->tail = deque->tail->next = node;
+ return;
+ }
+
+ node->next = node;
+ deque->head = deque->tail = node;
+}
+
+void history_push_element(CHANNEL_HISTORY_DEQUE *deque, RAW *raw) {
+ free_raw(deque->head->value);
+ deque->head->value = raw;
+ deque->tail = deque->head;
+ deque->head = deque->head->next;
+}
+
+void history_free_node(CHANNEL_HISTORY_NODE *node) {
+ free_raw(node->value);
+ free(node);
+}
+
+void deque_truncate_buffer(CHANNEL_HISTORY_DEQUE *deque, const int size) {
+ int i = size;
+ for (; i < deque->length; ++i) {
+ deque->head = deque->head->next;
+ history_free_node(deque->tail->next);
+ deque->tail->next = deque->head;
+ }
+ if (size == 0 && i > size) {
+ free(deque);
+ deque = NULL;
+ }
+}
+
+
+void free_channel_history(CHANNEL_HISTORY_DEQUE *deque) {
+ if (deque == NULL) return;
+ deque_truncate_buffer(deque, 0);
+}
+
+void update_chan_history_size(CHANNEL *chan) {
+ if (chan->history == NULL) return;
+ {
+ const int max_history_size = get_channel_max_history_size(chan);
+
+ if (max_history_size < chan->history->length) {
+ deque_truncate_buffer(chan->history, max_history_size);
+ }
+ }
+}
+
+
+CHANNEL_HISTORY_DEQUE *new_channel_history(void) {
+ struct CHANNEL_HISTORY_DEQUE *deque = xmalloc(sizeof(*deque));
+
+ deque->length = 0;
+ deque->filter = NULL;
+ deque->head = deque->tail = NULL;
+
+ return deque;
+}
+
+CHANNEL_HISTORY_DEQUE *init_channel_history(CHANNEL *chan, apeconfig *config) {
+ char *config_val = CONFIG_VAL(Channels, history_default_max_size, config);
+ if (config_val != NULL && atoi(config_val) > 0) {
+ CHANNEL_HISTORY_DEQUE *deque = new_channel_history();
+ add_property(&chan->properties, "max_history_size", config_val, EXTEND_STR, EXTEND_ISPRIVATE);
+
+ config_val = CONFIG_VAL(Channels, history_default_raw_filter, config);
+ if (config_val != NULL) {
+ S_TOUPPER(config_val);
+ if (strcmp(config_val, "ALL") != 0) {
+ deque->filter = config_val;
+ }
+ }
+
+ return deque;
+ }
+
+ return NULL;
+}
+
+
+/* preconditions: memory for raw has been allocated and will not be freed later elsewhere, maxsize>0 */
+void push_raw_to_channel_history(CHANNEL *chan, RAW *raw, apeconfig *config) {
+ if (chan == NULL || chan->history == NULL) {
+ return;
+ }
+
+ if (chan->history->filter != NULL) {
+ char *type = strstr(raw->data, "\"raw\":\"");
+
+ ITERATE_CONFIG_VAL(chan->history->filter, " ", {
+ if (type == NULL || strncmp(type+7, token, strlen(token)) != 0) {
+ free_raw(raw);
+ return;
+ }
+ });
+ }
+
+ if (chan->history->length == get_channel_max_history_size(chan)) {
+ history_push_element(chan->history, raw);
+ return;
+ }
+
+ history_append_element(chan->history, raw);
+}
+
+void post_channel_history(CHANNEL *chan, USERS *user, acetables *g_ape) {
+ if (get_channel_max_history_size(chan) > 0) {
+ CHANNEL_HISTORY_NODE *node = chan->history->head;
+
+ if (node != NULL) {
+ do {
+ post_raw(copy_raw_z(node->value), user, g_ape);
+ node = node->next;
+ } while (node != chan->history->head);
+ }
+ }
+
+}
+
View
57 src/channel_history.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2010 Philipp Fuehrer <pf@netzbeben.de>
+
+ This file is part of APE Server.
+ APE is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ APE is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with APE ; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* channel_history.h */
+
+#ifndef _CHANNEL_HISTORY_H
+#define _CHANNEL_HISTORY_H
+
+#include "main.h"
+#include "channel.h"
+#include "json.h"
+#include "raw.h"
+#include "extend.h"
+#include "config.h"
+#include "users.h"
+
+
+typedef struct CHANNEL_HISTORY_NODE
+{
+ struct RAW *value;
+ struct CHANNEL_HISTORY_NODE *next;
+} CHANNEL_HISTORY_NODE;
+
+typedef struct CHANNEL_HISTORY_DEQUE
+{
+ int length;
+ char *filter;
+ struct CHANNEL_HISTORY_NODE *head;
+ struct CHANNEL_HISTORY_NODE *tail;
+} CHANNEL_HISTORY_DEQUE;
+
+
+int get_channel_max_history_size(CHANNEL *chan);
+CHANNEL_HISTORY_DEQUE *init_channel_history(CHANNEL *chan, apeconfig *config);
+void free_channel_history(CHANNEL_HISTORY_DEQUE *deque);
+
+void push_raw_to_channel_history(CHANNEL *chan, RAW *raw, apeconfig *config);
+void update_chan_history_size(CHANNEL *chan);
+void post_channel_history(CHANNEL *chan, USERS *user, acetables *g_ape);
+
+#endif
View
5 src/config.h
@@ -47,5 +47,10 @@ void ape_config_free(apeconfig *conf);
#define CONFIG_VAL(section, key, srv) \
(ape_config_get_key(ape_config_get_section(srv, #section), #key) == NULL ? "" : ape_config_get_key(ape_config_get_section(srv, #section), #key))
+#define ITERATE_CONFIG_VAL(val, delims, yield) { \
+char *token = strtok((val), (delims)); while (token != NULL) { (yield); token = strtok(NULL, delims); } \
+}
+
+
#endif
View
1 src/extend.h
@@ -49,6 +49,7 @@ struct _extend
};
extend *get_property(extend *entry, const char *key);
+void *get_property_val(extend *entry, const char *key);
void clear_properties(extend **entry);
void del_property(extend **entry, const char *key);
//extend *add_property_str(extend **entry, char *key, char *val);
View
32 src/raw.c
@@ -22,6 +22,7 @@
#include "raw.h"
#include "users.h"
#include "channel.h"
+#include "channel_history.h"
#include "proxy.h"
#include "utils.h"
#include "plugins.h"
@@ -55,15 +56,15 @@ RAW *forge_raw(const char *raw, json_item *jlist)
new_raw->data = string->jstring;
free(string);
-
return new_raw;
}
int free_raw(RAW *fraw)
{
- if (--(fraw->refcount) <= 0) {
+ if (--(fraw->refcount) < 0) {
free(fraw->data);
free(fraw);
+ fraw = NULL;
return 0;
}
@@ -120,9 +121,10 @@ void post_raw_sub(RAW *raw, subuser *sub, acetables *g_ape)
void post_raw(RAW *raw, USERS *user, acetables *g_ape)
{
subuser *sub = user->subuser;
- while (sub != NULL) {
- post_raw_sub(copy_raw_z(raw), sub, g_ape);
- sub = sub->next;
+
+ while (sub != NULL) {
+ post_raw_sub(copy_raw_z(raw), sub, g_ape);
+ sub = sub->next;
}
}
@@ -134,6 +136,7 @@ void post_raw_restricted(RAW *raw, USERS *user, subuser *sub, acetables *g_ape)
if (sub == NULL) {
return;
}
+
while (tSub != NULL) {
if (sub != tSub) {
post_raw_sub(copy_raw_z(raw), tSub, g_ape);
@@ -152,6 +155,11 @@ void post_raw_channel(RAW *raw, struct CHANNEL *chan, acetables *g_ape)
if (chan == NULL || raw == NULL || chan->head == NULL) {
return;
}
+
+ if (get_channel_max_history_size(chan) > 0) {
+ push_raw_to_channel_history(chan, copy_raw_z(raw), g_ape->srv);
+ }
+
list = chan->head;
while (list) {
post_raw(raw, list->userinfo, g_ape);
@@ -168,8 +176,12 @@ void post_raw_channel_restricted(RAW *raw, struct CHANNEL *chan, USERS *ruser, a
if (chan == NULL || raw == NULL || chan->head == NULL) {
return;
}
+
+ if (get_channel_max_history_size(chan) > 0) {
+ push_raw_to_channel_history(chan, copy_raw_z(raw), g_ape->srv);
+ }
+
list = chan->head;
-
while (list) {
if (list->userinfo != ruser) {
post_raw(raw, list->userinfo, g_ape);
@@ -247,10 +259,16 @@ int post_to_pipe(json_item *jlist, const char *rawname, const char *pipe, subuse
post_raw(newraw, recver->pipe, g_ape);
break;
case CHANNEL_PIPE:
- if (((CHANNEL*)recver->pipe)->head != NULL && ((CHANNEL*)recver->pipe)->head->next != NULL) {
+ if (((CHANNEL*)recver->pipe)->head != NULL) {
json_set_property_objN(jlist, "pipe", 4, get_json_object_channel(recver->pipe));
newraw = forge_raw(rawname, jlist);
post_raw_channel_restricted(newraw, recver->pipe, sender, g_ape);
+
+ if ( ((CHANNEL*)recver->pipe)->head->next == NULL &&
+ newraw != NULL // paranoia
+ ) {
+ free_raw(newraw);
+ }
}
break;
case CUSTOM_PIPE:
View
1 src/users.h
@@ -199,6 +199,7 @@ enum {
#define RAW_LEFT "LEFT"
#define RAW_SETLEVEL "SETLVL"
#define RAW_SETTOPIC "SETTOPIC"
+#define RAW_SETFLAGS "SETFLAGS"
#define RAW_USER "USER"
#define RAW_ERR "ERR"
#define RAW_CHANNEL "CHANNEL"
View
9 src/utils.c
@@ -55,6 +55,15 @@ void s_tolower(char *upper, unsigned int len)
}
}
+void s_toupper(char *lower, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ lower[i] = toupper(lower[i]);
+ }
+}
+
long int itos(long int input, char *output, long int len)
{
int sign = 0, i = 1;
View
5 src/utils.h
@@ -40,6 +40,7 @@ char hex2int(unsigned char hex);
int urldecode(char *string);
int rand_n(int n);
void s_tolower(char *upper, unsigned int len);
+void s_toupper(char *upper, unsigned int len);
char *get_path(const char *full_path);
/* CONST_STR_LEN from lighttpd */
@@ -53,4 +54,8 @@ char *get_path(const char *full_path);
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
+#define S_TOLOWER(s) (s_tolower(s, strlen(s)))
+#define S_TOUPPER(s) (s_toupper(s, strlen(s)))
+
+
#endif

0 comments on commit e117997

Please sign in to comment.
Something went wrong with that request. Please try again.