[mw-devel] MW3 r1110 - in trunk: src talkhelp
psycodom at sucs.org
psycodom at sucs.org
Thu Nov 26 13:03:40 GMT 2009
Author: psycodom
Date: 2009-11-26 13:03:39 +0000 (Thu, 26 Nov 2009)
New Revision: 1110
Added:
trunk/src/uri.c
trunk/src/uri.h
trunk/talkhelp/uri
Modified:
trunk/src/Makefile
trunk/src/chattable.c
trunk/src/completion.c
trunk/src/js.c
trunk/src/log.c
trunk/src/sqlite.c
trunk/src/talker.c
trunk/src/talker.h
trunk/src/talker_privs.c
Log:
Adds a .uri command to allow editing/listing of the mwuri db
Also fixes a couple of bugs encountered along the way (notably a strdup(NULL) in sqlite.c
Modified: trunk/src/Makefile
===================================================================
--- trunk/src/Makefile 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/Makefile 2009-11-26 13:03:39 UTC (rev 1110)
@@ -99,7 +99,7 @@
topten.o sort.o tidyup.o gags.o script_inst.o script.o\
incoming.o command.o chattable.o alias.o frl.o hash.o vars.o expand.o\
mud.o mudtable.o files.o completion.o sentinel.o iconv.o gagtable.o \
-js.o sqlite.o ipc.o log.o
+js.o sqlite.o ipc.o log.o uri.o
$(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^
del_user: del_user.o perms.o strings.o
Modified: trunk/src/chattable.c
===================================================================
--- trunk/src/chattable.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/chattable.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -74,6 +74,7 @@
{"ungag" ,0x0002 ,1, "Usage: ungag <user>", "Remove the Gag on the user", t_ungag, 1},
{"unignore" ,0x0000 ,1, "Usage: unignore <user>", "Stop filtering user out so you can hear them", t_unignore, 1},
{"unprotect" ,0x0020 ,1, "Usage: unprotect <user>", "Remove protection from user", t_unprotect, 1},
+{"uri" ,0x0000 ,0, "Usage: uri [list [all|username] [n] | delete <id> | nsfw <id> | membersonly <id> | anonymous <id> | displaymode <full|short>]", "View/Edit the uris in the mwuri database", t_uri, 1},
{"variables" ,0x0200 ,0, "Usage: variables [mask]", "List script variables + contents [or starting with mask]", t_showvars, 1},
{"what" ,0x0000 ,0, "Usage: what", "See peoples status", t_what, 1},
{"whisper" ,0x0000 ,2, "Usage: whisper <user> <message>", "Send a message to a single user", t_whisper, 1},
Modified: trunk/src/completion.c
===================================================================
--- trunk/src/completion.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/completion.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -2,6 +2,7 @@
#include "bb.h"
#include "proto.h"
#include "script.h"
+#include "uri.h"
/*
modes: 0 - commands
@@ -58,6 +59,8 @@
{"ungag" ,1 ,1 ,1 ,part_who_talk},
{"unignore" ,1 ,1 ,-1 ,part_who},
{"unprotect" ,1 ,1 ,1 ,part_who_talk},
+{"uri" ,1 ,2 ,2 ,uri_arg_tc},
+{"uri" ,1 ,1 ,1 ,uri_action_tc},
{"whisper" ,1 ,1 ,1 ,part_who_talk},
{"zod" ,1 ,1 ,1 ,part_who_talk},
Modified: trunk/src/js.c
===================================================================
--- trunk/src/js.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/js.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -758,9 +758,14 @@
// printf("dbdata_to_jsarray: data @ %p -", (void *)data->field[i]);
// printf("%s", data->field[i]);
// printf(" -> JSString @ %p\n", (void *)jsstr);
- jsstr = JS_NewStringCopyZ(cx, data->field[i]);
- jv = STRING_TO_JSVAL(jsstr);
+ if(data->field[i] != NULL) {
+ jsstr = JS_NewStringCopyZ(cx, data->field[i]);
+ jv = STRING_TO_JSVAL(jsstr);
+ } else {
+ jv = JSVAL_NULL;
+ }
JS_SetElement(cx, jsdata, i, &jv);
+
}
JS_RemoveRoot(cx, jsdata);
Modified: trunk/src/log.c
===================================================================
--- trunk/src/log.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/log.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -26,7 +26,7 @@
#include "js.h"
#include "files.h"
#include "log.h"
-
+#include "uri.h"
#include "rooms.h"
#include "ipc.h"
#include "sqlite.h"
@@ -65,9 +65,6 @@
uint32_t flags;
};
-#define URLFLAG_NSFW 0x0001
-#define URLFLAG_ANON 0x0002
-#define URLFLAG_SUCS 0x0004
struct uripatt urilist[] = {
{"^http://$", REG_ICASE, NULL, IGNORE, 0},
@@ -313,29 +310,16 @@
block_free(body);
/* fishing mission complete, store the results */
-
- flags[0]=0;
- if (uri->flags & URLFLAG_NSFW) {
- int n = strlen(flags);
- snprintf(&flags[n], sizeof(flags)-n, "%snsfw", flags[0]==0?"":" ");
- }
- if (uri->flags & URLFLAG_ANON) {
- int n = strlen(flags);
- snprintf(&flags[n], sizeof(flags)-n, "%sanon", flags[0]==0?"":" ");
- }
- if (uri->flags & URLFLAG_SUCS) {
- int n = strlen(flags);
- snprintf(&flags[n], sizeof(flags)-n, "%ssucs", flags[0]==0?"":" ");
- }
-
- snprintf(path,sizeof(path),"%s/mwuri.db", STATEDIR);
- char *query = sqlite3_mprintf("INSERT INTO mwuri (user, url, added, flags, title, tags) values (%Q,%Q,datetime('now'),%Q,%Q,%Q)", user->name, url, (uri->flags&URLFLAG_NSFW)?"nsfw":NULL, title, deli==NULL?NULL:deli->p_buffer);
- res = db_query(path, query, 1);
+
+ uri_make_flags_str(uri->flags, flags, sizeof(flags));
+
+ char *query = sqlite3_mprintf("INSERT INTO mwuri (user, url, added, flags, title, tags) values (%Q,%Q,datetime('now'),%Q,%Q,%Q)", user->name, url, flags, title, deli==NULL?NULL:deli->p_buffer);
+ res = db_query(MWURI_DB, query, 1);
if (res == NULL) {
- res = db_query(path, "CREATE TABLE mwuri (id INTEGER PRIMARY KEY AUTOINCREMENT, user text, url text, added text, flags text, title text, tags text )", 0);
+ res = db_query(MWURI_DB, "CREATE TABLE mwuri (id INTEGER PRIMARY KEY AUTOINCREMENT, user text, url text, added text, flags text, title text, tags text )", 0);
if (res != NULL) {
db_free(res);
- res = db_query(path, query, 0);
+ res = db_query(MWURI_DB, query, 0);
}
}
db_free(res);
@@ -352,17 +336,15 @@
static void *file_tag(void * data)
{
struct taghit *tag = data;
- char path[1024];
struct db_result *res;
- snprintf(path,sizeof(path),"%s/mwuri.db", STATEDIR);
char *query = sqlite3_mprintf("INSERT INTO mwtag (user, tag, added, line) values (%Q,%Q,datetime('now'),%Q)", user->name, tag->tag, tag->line);
- res = db_query(path, query, 1);
+ res = db_query(MWURI_DB, query, 1);
if (res == NULL) {
- res = db_query(path, "CREATE TABLE mwtag (id INTEGER PRIMARY KEY AUTOINCREMENT, user text, tag text, added text, line text )", 0);
+ res = db_query(MWURI_DB, "CREATE TABLE mwtag (id INTEGER PRIMARY KEY AUTOINCREMENT, user text, tag text, added text, line text )", 0);
if (res != NULL) {
db_free(res);
- res = db_query(path, query, 0);
+ res = db_query(MWURI_DB, query, 0);
}
}
db_free(res);
@@ -376,17 +358,15 @@
/* store the doing/status string in the db */
void catchdoing(const char *what)
{
- char path[1024];
struct db_result *res;
- snprintf(path,sizeof(path),"%s/mwuri.db", STATEDIR);
char *query = sqlite3_mprintf("INSERT INTO mwdoing (user, added, doing) values (%Q,datetime('now'),%Q)", user->name, what);
- res = db_query(path, query, 1);
+ res = db_query(MWURI_DB, query, 1);
if (res == NULL) {
- res = db_query(path, "CREATE TABLE mwdoing (id INTEGER PRIMARY KEY AUTOINCREMENT, user text, added text, doing text )", 0);
+ res = db_query(MWURI_DB, "CREATE TABLE mwdoing (id INTEGER PRIMARY KEY AUTOINCREMENT, user text, added text, doing text )", 0);
if (res != NULL) {
db_free(res);
- res = db_query(path, query, 0);
+ res = db_query(MWURI_DB, query, 0);
}
}
db_free(res);
Modified: trunk/src/sqlite.c
===================================================================
--- trunk/src/sqlite.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/sqlite.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -60,7 +60,13 @@
/* Copy the data in and attach it */
ndata = malloc(sizeof(*ndata));
ndata->field = calloc(ncols+1, sizeof(char *));
- for (i=0;i<ncols;i++) ndata->field[i] = strdup(row[i]);
+ for (i=0;i<ncols;i++) {
+ if(row[i] != NULL) {
+ ndata->field[i] = strdup(row[i]);
+ } else {
+ ndata->field[i] = NULL;
+ }
+ }
ndata->row = query->rows - 1;
ndata->next = query->data;
query->data = ndata;
@@ -249,8 +255,11 @@
/* throw away the returned rows */
ndata = result->data;
while (ndata != NULL) {
- for (i=0;i<result->cols;i++)
- free(ndata->field[i]);
+ for (i=0;i<result->cols;i++) {
+ if(ndata->field[i]) {
+ free(ndata->field[i]);
+ }
+ }
free(ndata->field);
nnext = ndata->next;
free(ndata);
Modified: trunk/src/talker.c
===================================================================
--- trunk/src/talker.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/talker.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -27,6 +27,8 @@
#include "rooms.h"
#include "ipc.h"
#include "log.h"
+#include "user.h"
+#include "uri.h"
#include "alias.h"
extern Alias bind_list;
@@ -1386,6 +1388,48 @@
update_user(user,userposn);
}
+void t_uri(CommandList *cm, int argc, char **argv, char *args)
+{
+ uriActionList *al = uritable;
+ int wiz=0, num;
+ char c;
+
+ if(argc == 1) {
+ // default action - list last 10 uris
+ uri_list_display(10, NULL);
+ return;
+ }
+
+ if (u_god(user->status)) {
+ wiz=1;
+ }
+
+ while(al->action)
+ {
+ if( strcasecmp(al->action, argv[1]) == 0 // we have a valid action
+ && argc-1 >= al->min_argc // it has enough args
+ && argc-1 <= al->max_argc // and doesn't have too many args
+ && ( !al->needs_wiz || (al->needs_wiz && wiz)) ) // and it either doesn't need wiz or we are wiz
+ {
+ al->function(argc -1, &argv[1], al->needs_wiz && wiz);
+ return;
+ }
+ al++;
+ }
+
+ if(argc == 2) // check for the posibility we have ".uri n" (same as .uri list * n)
+ {
+ if(sscanf(argv[1], "%d%c", &num, &c) == 1) { // check the arg is an int
+ if(num > 0) {
+ uri_list_display(num, NULL);
+ return;
+ }
+ }
+ }
+
+ printf("%s\n", cm->ArgError);
+}
+
void t_chaton(void)
{
char text[MAXTEXTLENGTH];
Modified: trunk/src/talker.h
===================================================================
--- trunk/src/talker.h 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/talker.h 2009-11-26 13:03:39 UTC (rev 1110)
@@ -54,6 +54,7 @@
void t_showvars(CommandList *cm, int argc, char **argv, char *args);
void t_linewrap(CommandList *cm, int argc, char **argv, char *args);
void t_mwrc(CommandList *cm, int argc, char **argv, char *args);
+void t_uri(CommandList *cm, int argc, char **argv, char *args);
void t_chaton(void);
void chat_say(char *text);
Modified: trunk/src/talker_privs.c
===================================================================
--- trunk/src/talker_privs.c 2009-11-22 16:36:02 UTC (rev 1109)
+++ trunk/src/talker_privs.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -604,7 +604,7 @@
ptr=0;
len=strlen(text);
}
-
+
while (gaglist[ptr].name!=NULL)
{
if ((len==0 || !strncasecmp(gaglist[ptr].name, text, len)) && strcmp(gaglist[ptr].name, ""))
Added: trunk/src/uri.c
===================================================================
--- trunk/src/uri.c (rev 0)
+++ trunk/src/uri.c 2009-11-26 13:03:39 UTC (rev 1110)
@@ -0,0 +1,702 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <readline/readline.h>
+
+#include "bb.h"
+#include "user.h"
+#include "uri.h"
+#include "sqlite.h"
+
+extern struct person *user;
+
+// uri action table
+// action, minargc, maxargc, tcmode, needs su, function
+// tcmode: 0: no tabcomplete 1: always tc 2: tc only after first char matched (su edit functions)
+uriActionList uritable[]={
+ { "list" , 1, 3, 1, 0, uri_list },
+ { "-log" , 2, 2, 0, 0, uri_delete },
+ { "delete" , 2, 2, 1, 0, uri_delete },
+ { "del" , 2, 2, 0, 0, uri_delete },
+ { "!delete" , 2, 2, 2, 1, uri_delete },
+ { "!del" , 2, 2, 0, 1, uri_delete },
+ { "nsfw" , 2, 2, 1, 0, uri_nsfw },
+ { "!nsfw" , 2, 2, 2, 1, uri_nsfw },
+ { "membersonly" , 2, 2, 1, 0, uri_members_only },
+ { "!membersonly" , 2, 2, 2, 1, uri_members_only },
+ { "sucs" , 2, 2, 0, 0, uri_members_only },
+ { "anonymous" , 2, 2, 1, 0, uri_anon },
+ { "!anonymous" , 2, 2, 2, 1, uri_anon },
+ { "anon" , 2, 2, 0, 0, uri_anon },
+ { "displaymode" , 1, 2, 1, 0, uri_display_mode },
+ { NULL, 0, 0, 1, 1, NULL }
+};
+
+// uri flags
+// integer flag, db string, description used (un)setting flag, description used in list
+uriFlagList uriflagtable[] = {
+ { URLFLAG_NSFW, "nsfw", "NSFW", "\033R-NSFW\033--" },
+ { URLFLAG_ANON, "anon", "anonymous on web", "[Anon on web]" },
+ { URLFLAG_SUCS, "sucs", "members-only", "(Members Only)" },
+ { 0, NULL, NULL, NULL }
+};
+
+// turns the db flag string into a bitwise flag field
+int uri_parse_flags(const char *flagstr)
+{
+ int flags = 0;
+ uriFlagList *fl = uriflagtable;
+ if(!flagstr) {
+ return 0;
+ }
+ while(fl->flag)
+ {
+ if(strcasestr(flagstr, fl->flagstr)) {
+ flags |= fl->flag;
+ }
+ fl++;
+ }
+ return flags;
+}
+
+// creates a string of database flags for the bitwise flags
+void uri_make_flags_str(int flags, char *flagstr, int len)
+{
+ int n=0;
+ uriFlagList *fl = uriflagtable;
+
+ flagstr[0] = '\0';
+ while(fl->flag)
+ {
+ if(flags & fl->flag)
+ {
+ n += snprintf(&flagstr[n], len-n, "%s%s", n==0?"":" ", fl->flagstr);
+ }
+ fl++;
+ }
+}
+
+// creates a the flag descriptions show in uri list from the database flags string
+void uri_make_flags_description(char *shortflags, char *flagstr, int len)
+{
+ int n=0;
+ uriFlagList *fl = uriflagtable;
+
+ flagstr[0] = '\0';
+ while(fl->flag)
+ {
+ if(strcasestr(shortflags, fl->flagstr))
+ {
+ n += snprintf(&flagstr[n], len-n, " %s", fl->list_desc);
+ }
+ fl++;
+ }
+}
+
+// returns the long description for flag
+// should be duplicated if you want to edit it
+char *uri_get_flag_description(int flag)
+{
+ uriFlagList *fl = uriflagtable;
+
+ while(fl->flag)
+ {
+ if(flag == fl->flag)
+ {
+ return fl->long_desc;
+ }
+ fl++;
+ }
+ return NULL;
+}
+
+// display <number> uris posted by <username> (or all users if username is NULL)
+void uri_list_display(int number, const char * username)
+{
+ char *query;
+ struct db_result *res;
+ struct db_data *node;
+ int width, i, len;
+ char url_line[MAXTEXTLENGTH];
+ char *mode;
+ int disp_mode=0;
+ char flagstr[1024]="";
+
+ if(username == NULL) {
+ query = sqlite3_mprintf("SELECT id,added,user,url,title,flags FROM mwuri ORDER BY id DESC LIMIT %d", number);
+ } else {
+ query = sqlite3_mprintf("SELECT id,added,user,url,title,flags FROM mwuri WHERE user=%Q ORDER BY id DESC LIMIT %d", username, number);
+ }
+ res = db_query(MWURI_DB, query, 1);
+ fflush(stdout);
+ if(res == NULL) {
+ printf(".uri database lookup failed\n");
+ } else {
+ if(res->rows < 1)
+ {
+ if(username)
+ {
+ printf("%s has not posted any uris\n", username);
+ }
+ else
+ {
+ printf("There are not currently any uris in mwuri\n");
+ }
+ }
+ else if(res->rows < number)
+ {
+ printf("Displaying all uris posted to milliways%s%s:\n", username ? " by user " : "", username ? username : "");
+ }
+ else
+ {
+ printf("Displaying the last %d uri%s posted to milliways%s%s:\n", res->rows, res->rows==1? "s":"", username ? " by user " : "", username ? username : "");
+ }
+ // pick up the display mode from the private db
+ // we default to short if we don't get anything from the db
+ mode = userdb_get(USERDB_PRIVATE, user->name, "mwuri_display_mode");
+ if(mode)
+ {
+ if(strcmp(mode, "full")==0)
+ {
+ disp_mode = 1;
+ }
+ }
+ node = res->data;
+ width = screen_w();
+ if(width > MAXTEXTLENGTH - 1) {
+ width = MAXTEXTLENGTH - 1;
+ }
+ url_line[width]='\0';
+ while(node) {
+ char *id = node->field[0];
+ char *added = node->field[1];
+ char *username = node->field[2];
+ char *url = node->field[3];
+ char *title = node->field[4];
+ uri_make_flags_description(node->field[5], flagstr, sizeof(flagstr)); // flags = node->field[5]
+
+ snprintf(url_line, width, "#\033G-%s\033-- [%s] <%s>%s\n", id, added, username, flagstr );
+ display_message(url_line, 0, 1);
+
+ if(title != NULL) {
+ len = strlen(title);
+ for(i = 0; i<len; i++) {
+ if(title[i]=='\n') title[i]=' ';
+ }
+ }
+ if(disp_mode)
+ {
+ // in full display mode we just show the whole url + title
+ snprintf(url_line, MAXTEXTLENGTH-1, " %s%s%s", url, title ? " | ":"", title ? title:"");
+
+ }
+ else
+ {
+ // in short display mode we try to fit url+title onto one line and shorten if it doesn't fit
+ // the whole url is always shown
+ if(strlen(url)+6 > width)
+ {
+ snprintf(url_line, width+1, " %s", url); // ' '.uri." | " is wider than the screen so just show the who url
+ }
+ else
+ {
+ if(snprintf(url_line, width+1, " %s%s%s", url, title ? " | ":"", title ? title:"") > width)
+ {
+ // line + title is wider than the screen so put ... at the end
+ url_line[width - 1] = '.';
+ url_line[width - 2] = '.';
+ url_line[width - 3] = '.';
+ }
+ }
+ }
+ display_message(url_line, 0, 1);
+ node = node->next;
+ }
+ db_free(res);
+ }
+ sqlite3_free(query);
+}
+
+/* parse the .uri list command and display uris if appropriate */
+void uri_list(int argc, char **argv, int wiz)
+{
+ char *username = NULL; // default is to display everyone's uris
+ int number = 10; // default is to display 10 uris
+ struct person *list_user = NULL;
+ char c;
+
+ if(argc == 1) // just '.uri list'
+ {
+ username = user->name;
+ }
+ else if(strcasecmp(argv[1], "*") == 0) // wants all uris
+ {
+ // username is already NULL and will thus select everyone
+ if(argc==3)
+ {
+ if(sscanf(argv[2], "%d%c", &number, &c) == 1)
+ {
+ if(number < 1)
+ {
+ printf(".uri list * - can't list <1 uris\n");
+ return;
+ }
+ }
+ else
+ {
+ printf(".uri list * - last parameter was not a positive integer\n");
+ return;
+ }
+
+ }
+ if(argc>3)
+ {
+ printf(".uri list * - too many parameters\n");
+ return;
+ }
+
+ }
+ else if( (list_user = user_get(argv[1])) != NULL) // is a real user
+ {
+ username = list_user->name;
+ if(argc==3)
+ {
+ if(sscanf(argv[2], "%d%c", &number, &c) == 1)
+ {
+ if(number < 1)
+ {
+ free(list_user);
+ printf(".uri list %s - can't list <1 uris\n", argv[1]);
+ return;
+ }
+ }
+ else
+ {
+ free(list_user);
+ printf(".uri list %s - last parameter was not a positive integer\n", argv[1]);
+ return;
+ }
+ }
+ if(argc>3)
+ {
+ free(list_user);
+ printf(".uri list %s - too many parameters\n", argv[1]);
+ return;
+ }
+ }
+ else // possibly we have '.uri list n' or we might have garbage
+ {
+ if(argc==2)
+ {
+ if(sscanf(argv[1], "%d%c", &number, &c) == 1)
+ {
+ if(number < 1)
+ {
+ printf(".uri list - can't list <1 uris\n");
+ return;
+ }
+ // we have a .uri list n
+ username = user->name;
+ }
+ else
+ {
+ printf(".uri list - last parameter was not *, a username or a positive integer\n");
+ return;
+ }
+ }
+ if(argc>2)
+ {
+ printf(".uri list - invalid parameters\n");
+ return;
+ }
+
+ }
+
+ uri_list_display(number, username);
+
+ if(list_user) {
+ free(list_user);
+ }
+}
+
+// checks an id supplied to uri_delete/nsfw etc. is valid or creates an id if the user specified 'last'
+// if wiz is true "last" will return the the last uri in mwuri otherwise it is the current users last uri
+// returns 0 if the id is not valid.
+unsigned int uri_get_id(char *idstr, int wiz)
+{
+ unsigned int id;
+ char c;
+ char *query;
+ struct db_result *res;
+
+ if( strcasecmp( "last", idstr ) == 0)
+ {
+ id=0;
+ if(wiz)
+ {
+ query = sqlite3_mprintf("SELECT id FROM mwuri ORDER BY id DESC LIMIT 1");
+ }
+ else
+ {
+ query = sqlite3_mprintf("SELECT id FROM mwuri WHERE user=%Q ORDER BY id DESC LIMIT 1", user->name );
+ }
+ res = db_query(MWURI_DB, query, 0);
+ sqlite3_free(query);
+ if(res)
+ {
+ if(res->rows > 0)
+ {
+ sscanf(res->data->field[0], "%u", &id);
+ }
+ db_free(res);
+ }
+ return id;
+ }
+ else if( sscanf(idstr, "%u%c", &id, &c) == 1 )
+ {
+ return id;
+ }
+ else if( sscanf(idstr, "#%u%c", &id, &c) == 1)
+ {
+ return id;
+ }
+ return 0;
+}
+
+// deletes uri argv[1] if argv[1] is the id of a valid uri or "last"
+// if wiz is true any uri can be deleted otherwise only the current user's
+void uri_delete(int argc, char **argv, int wiz)
+{
+ unsigned int id;
+ char *query;
+ struct db_result *res;
+ char mesg[MAXTEXTLENGTH];
+ char *del_query;
+ struct db_result *del_res;
+ int owner;
+ char answer[10];
+ char *username, *uri, *added;
+
+ if((id = uri_get_id(argv[1], wiz)) > 0 )
+ {
+ query = sqlite3_mprintf("SELECT user,url,added FROM mwuri WHERE id=%d", id);
+ res = db_query(MWURI_DB, query, 1);
+ if(res)
+ {
+ if(res->rows > 0)
+ {
+ username = res->data->field[0];
+ uri = res->data->field[1];
+ added = res->data->field[2];
+ owner = (strcmp(user->name, username)==0);
+
+ if(owner || wiz)
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "Are you sure you want to delete %s%s uri %s from mwuri?", owner? "your":username, owner? "":"'s", uri);
+ display_message(mesg, 0, 1);
+ get_str(answer, 5);
+ if (answer[0]=='y' || answer[0]=='Y')
+ {
+ del_query = sqlite3_mprintf("DELETE FROM mwuri WHERE id=%d", id);
+ del_res = db_query(MWURI_DB, del_query, 1);
+
+ if(del_res)
+ {
+ free(del_res);
+ snprintf(mesg, MAXTEXTLENGTH-1, "\03304%s has just deleted %s's uri %s [%s] from mwuri", user->name, username, uri, added);
+ broadcast(1, "%s", mesg);
+ snprintf(mesg, MAXTEXTLENGTH-1, "MWURI %s deleted uri: %s <%s> [%s]", user->name, username, uri, added);
+ mwlog("%s", mesg);
+ }
+ else
+ {
+ printf("A db error occured trying to delete uri #%d\n", id);
+ }
+ sqlite3_free(del_query);
+ }
+ }
+ else
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "uri #%d %s was not posted by you. You cannot delete it", id, uri);
+ display_message(mesg, 0, 1);
+ }
+ }
+ else
+ {
+ printf("uri %s: couldn't find uri #%d to delete\n", argv[0], id);
+ }
+ db_free(res);
+ sqlite3_free(query);
+ }
+ else
+ {
+ printf("uri %s: A db error occured while trying to find uri %s\n", argv[0], argv[1]);
+ }
+ }
+ else
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "uri %s: %s is not a valid uri id", argv[0], argv[1]);
+ display_message(mesg, 0, 1);
+ }
+}
+
+// toggles flag uri argv[1] if argv[1] is the id of a valid uri or "last"
+// if wiz then any uri can be modified otherwise only the current user's
+void uri_set_flag(int argc, char **argv, int wiz, int flag)
+{
+ unsigned int id;
+ char mesg[MAXTEXTLENGTH];
+ char *query, *update_query;
+ struct db_result *res, *update_res;
+ int owner;
+ char answer[10];
+ char *username, *uri, *added;
+ int flags;
+ char flagstr[1024];
+ char *desc_str = uri_get_flag_description(flag);
+
+ if(desc_str == NULL) {
+ printf("uri: whoops, someone needs to debug\n");
+ return;
+ }
+
+ if((id = uri_get_id(argv[1], wiz)) > 0 )
+ {
+ query = sqlite3_mprintf("SELECT user,url,flags,added FROM mwuri WHERE id=%d", id);
+ res = db_query(MWURI_DB, query, 1);
+ if(res)
+ {
+ if(res->rows > 0)
+ {
+ username = res->data->field[0];
+ uri = res->data->field[1];
+ flags = uri_parse_flags(res->data->field[2]);
+ added = res->data->field[3];
+ owner = (strcmp(user->name, username)==0);
+
+ if(owner || wiz)
+ {
+ if(flags & flag)
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "%s%s uri %s is already flaged as %s, do you want to unflag it?", owner? "your":username, owner? "":"'s", uri, desc_str);
+ }
+ else
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "Are you sure you want to flag %s%s uri %s as %s?", owner? "your":username, owner? "":"'s", uri, desc_str);
+ }
+ display_message(mesg, 0, 1);
+ get_str(answer, 5);
+ if (answer[0]=='y' || answer[0]=='Y')
+ {
+ flags ^= flag; // toggle flag
+
+ uri_make_flags_str(flags, flagstr, sizeof(flagstr));
+
+ update_query = sqlite3_mprintf("UPDATE mwuri SET flags=%Q WHERE id=%d", flagstr, id);
+ update_res = db_query(MWURI_DB, update_query, 1);
+
+ if(update_res)
+ {
+ free(update_res);
+ snprintf(mesg, MAXTEXTLENGTH-1, "\03304%s has just %sset the %s flag on %s's uri %s [%s] in mwuri", user->name, flag&flags?"":"un", desc_str, username, uri, added);
+ broadcast(1, "%s", mesg);
+ snprintf(mesg, MAXTEXTLENGTH-1, "MWURI %s %sset %s flag on uri: %s <%s> [%s]", user->name, flag&flags?"":"un", desc_str, username, uri, added);
+ mwlog("%s", mesg);
+ }
+ else
+ {
+ printf("A db error occured trying to change flags on uri #%d\n", id);
+ }
+ sqlite3_free(update_query);
+ }
+ }
+ else
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "uri #%d %s was not posted by you. You cannot modify it", id, uri);
+ display_message(mesg, 0, 1);
+ }
+ }
+ else
+ {
+ printf("uri %s: couldn't find uri #%d to modify\n", argv[0], id);
+ }
+ db_free(res);
+ sqlite3_free(query);
+ }
+ }
+ else
+ {
+ snprintf(mesg, MAXTEXTLENGTH-1, "uri %s: %s is not a valid uri id", argv[0], argv[1]);
+ display_message(mesg, 0, 1);
+ }
+
+}
+
+// these 3 flag functions call the man set_flag with the right flag
+void uri_nsfw(int argc, char **argv, int wiz)
+{
+ uri_set_flag(argc, argv, wiz, URLFLAG_NSFW);
+}
+
+void uri_members_only(int argc, char **argv, int wiz)
+{
+ uri_set_flag(argc, argv, wiz, URLFLAG_SUCS);
+}
+
+void uri_anon(int argc, char **argv, int wiz)
+{
+ uri_set_flag(argc, argv, wiz, URLFLAG_ANON);
+}
+
+// sets full or short display mode for uri list
+void uri_display_mode(int argc, char **argv, int wiz)
+{
+ char *mode = userdb_get(USERDB_PRIVATE, user->name, "mwuri_display_mode");
+ char default_mode[] = "short";
+ if(!mode)
+ {
+ mode = default_mode;
+ }
+
+ if(argc == 1)
+ {
+ printf("Current uri list mode is: %s\n", mode ? mode:"short");
+ }
+ else
+ {
+ if(strcasecmp(argv[1],"full")==0)
+ {
+ userdb_set(USERDB_PRIVATE, user->name, "mwuri_display_mode", "full");
+ if(strcasecmp(mode, "full")==0)
+ {
+ printf("You are already using full uri list display mode\n");
+ }
+ else
+ {
+ printf("uri list display mode set to full\n");
+ }
+ }
+ else if(strcasecmp(argv[1],"short")==0)
+ {
+ userdb_set(USERDB_PRIVATE, user->name, "mwuri_display_mode", "short");
+ if(strcasecmp(mode, "short")==0)
+ {
+ printf("You are already using short uri list display mode\n");
+ }
+ else
+ {
+ printf("uri list display mode set to short\n");
+ }
+ }
+ else
+ {
+ printf("Usage: uri displaymode [full|short]\n");
+ }
+ }
+
+ if(mode != default_mode)
+ {
+ free(mode);
+ }
+}
+
+// sorts tab commpletion for the uri command
+char *uri_action_tc(const char *text, int state)
+{
+ static int i=0;
+ static int len=0;
+ static int wiz=0;
+ int do_tc=0;
+ char *c;
+
+ if (state==0)
+ {
+ i=0;
+ len=strlen(text);
+ wiz = u_god(user->status);
+ }
+
+ while (uritable[i].action!=NULL)
+ {
+ if(len==0 && uritable[i].tc_mode==1)
+ {
+ // if len is 0 we tc all actions with a tc_mode 1 - tc_mode 2 are the su !edit functions for altering others uris
+ do_tc = 1;
+ }
+ if(len > 0 && (!strncasecmp(uritable[i].action, text, len)) && uritable[i].tc_mode )
+ {
+ // if we have the first char(s) then all non hidden actions can be shown
+ do_tc = 1;
+ }
+ if(!strcmp(uritable[i].action, ""))
+ {
+ do_tc = 0;
+ }
+ if(uritable[i].needs_wiz && !wiz)
+ {
+ // if the action needs wiz and we haven't got wiz we don't tc
+ do_tc = 0;
+ }
+ if(do_tc)
+ {
+ c=dupstr(uritable[i].action,"");
+ i++;
+ return(c);
+ }
+ i++;
+ }
+ return(NULL);
+}
+
+char *uri_displaymodes[] = { "short", "full", NULL };
+
+// tab completes arguments for the uri list and uri displaymode commands
+// list: a username
+// displaymode: short | full
+char *uri_arg_tc(const char *text, int state)
+{
+ static int type=0;
+ static int ptr=0;
+ static int len=0;
+ char *c;
+
+ if (state==0)
+ {
+ type = 0;
+ ptr = 0;
+ len = strlen(text);
+
+ if(strcasestr(rl_line_buffer, " list "))
+ {
+ type = 1;
+ }
+ if(strcasestr(rl_line_buffer, " displaymode "))
+ {
+ type = 2;
+ }
+ }
+
+ if(type == 1)
+ {
+ // tab complete .uri list. part_user function handles it
+ return(part_user(text, state));
+ }
+ if(type == 2)
+ {
+ // tab complete .uri displaymode
+ while (uri_displaymodes[ptr]!=NULL)
+ {
+ if ((len==0 || !strncasecmp(uri_displaymodes[ptr], text, len)) && strcmp(uri_displaymodes[ptr], ""))
+ {
+ c=dupstr(uri_displaymodes[ptr],"");
+ ptr++;
+ return(c);
+ }
+ ptr++;
+ }
+
+ }
+ return(NULL);
+}
+
Added: trunk/src/uri.h
===================================================================
--- trunk/src/uri.h (rev 0)
+++ trunk/src/uri.h 2009-11-26 13:03:39 UTC (rev 1110)
@@ -0,0 +1,40 @@
+#define URLFLAG_NSFW 0x0001
+#define URLFLAG_ANON 0x0002
+#define URLFLAG_SUCS 0x0004
+
+#define MWURI_DB STATEDIR"/mwuri.db"
+
+
+typedef struct uriaction
+{
+ char *action;
+ int min_argc;
+ int max_argc;
+ int tc_mode;
+ int needs_wiz;
+ void (*function)(int, char **, int);
+} uriActionList;
+
+typedef struct uriflag
+{
+ int flag;
+ char *flagstr;
+ char *long_desc;
+ char *list_desc;
+} uriFlagList;
+
+extern uriActionList uritable[];
+
+void uri_make_flags_str(int flags, char *flagstr, int len);
+
+void uri_list_display(int number, const char * username);
+
+void uri_list(int argc, char **argv, int wiz);
+void uri_delete(int argc, char **argv, int wiz);
+void uri_nsfw(int argc, char **argv, int wiz);
+void uri_members_only(int argc, char **argv, int wiz);
+void uri_anon(int argc, char **argv, int wiz);
+void uri_display_mode(int argc, char **argv, int wiz);
+
+char *uri_action_tc(const char *text, int state);
+char *uri_arg_tc(const char *text, int state);
Added: trunk/talkhelp/uri
===================================================================
--- trunk/talkhelp/uri (rev 0)
+++ trunk/talkhelp/uri 2009-11-26 13:03:39 UTC (rev 1110)
@@ -0,0 +1,47 @@
+[1mNAME[0m
+ uri - view/edit the mwuri db
+
+[1mSYNOPSIS[0m
+ [1muri[0m [[4mNUMBER[0m]
+ [1muri list[0m [[4mUSERNAME | *[0m] [[4mNUMBER[0m]
+
+ [1muri delete[0m [4mID[0m
+ [1muri nsfw[0m [4mID[0m
+ [1muri membersonly[0m [4mID[0m
+ [1muri anonymous[0m [4mID[0m
+
+ [1muri displaymode[0m [4mshort | full[0m
+
+[1mDESCRIPTION[0m
+ [1muri[0m allows you to view or edit entires in the mwuri db.
+
+ With no parameters it will list the last 10 uris from all users.
+
+ [1muri list[0m lists the last [4mNUMBER[0m uris posted by user [4mUSERNAME[0m or [4m*[0m for
+ all users. If [4mNUMBER[0m is ommited it defaults to 10. If neither
+ [[4mUSERNAME[0m] or [[4m*[0m] are used it will display your own entries.
+
+ [1muri delete[0m allows you to delete uri [4mID[0m from the mwuri db if you posted it.
+ [4mID[0m is as supplied by the [1muri list[0m command. Can also be accessed using
+ [1muri -log[0m or [1muri del[0m.
+
+ [1muri nsfw[0m toggles the "not safe for work"(NSFW) flag for uri [4mID[0m in the mwuri
+ db if you posted it. [4mID[0m is as supplied by the [1muri list[0m command.
+
+ [1muri membersonly[0m toggles the "members-only" flag for uri [4mID[0m in the mwuri db
+ if you posted it. [4mID[0m is as supplied by the [1muri list[0m command. Can also
+ be accessed using [1muri sucs[0m.
+
+ [1muri anonymous[0m toggles the "anonymous on web" flag for uri [4mID[0m in the mwuri
+ db if you posted it. [4mID[0m is as supplied by the [1muri list[0m command. Can also
+ be accessed using [1muri sucs[0m.
+
+ *Superusers may add ! to the start of any edit command to edit other users
+ uris.*
+
+ [1muri displaymode[0m lets you set the display mode for the uri line of the
+ [1muri list[0m command. When [4mshort[0m the uri+title will only take up more than one
+ line on your terminal if the uri itself is longer than the width of your
+ terminal (the title is truncated to fit on one line). When [4mfull[0m the
+ uri+title are displayed in full.
+
More information about the mw-devel
mailing list