Commit 12d965b1 authored by stettberger's avatar stettberger

Added the basic Buddylist

parent 0f4ed577
......@@ -4,7 +4,7 @@ DESTDIR=
TARGET=si
SILCINCLUDE=/usr/include/silc
SILCLIB=/usr/lib/silc
FILES=si.c mit.c mm.c
FILES=si.c mit.c mm.c buddylist.c
CFLAGS=-I${SILCINCLUDE} -Wall -ggdb
LDFLAGS=-L${SILCLIB} -lsilc -lsilcclient -lpthread -ldl
......
/*
* si - silc improved - minimalistic silc client
*
* Copyright (C) 2006 Christian Dietrich <stettberger@gmx.de>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*/
/* Buddylist stuff */
void add_pubkey_callback(SilcClient client, SilcClientConnection conn,
SilcClientEntry *clients, SilcUInt32 clients_count,
void *context);
void
add_buddy(SilcClientEntry client) {
Buddy new=calloc(1, sizeof (Buddy)), tmp;
NULL_TEST(new);
new->client=client;
if(buddies) {
for (tmp=buddies; tmp->next; tmp=tmp->next);
tmp->next=new;
}
else
buddies=new;
}
void rm_buddy(SilcClientEntry client){
Buddy del, tmp;
if ( buddies->client==client)
buddies=buddies->next;
for(del=buddies; del->next; del=del->next)
if(del->next->client==client){
tmp=del->next;
del->next=del->next->next;
free(tmp);
}
}
void add_pubkey(char *pubkey) {
SilcBuffer attr=NULL;
SilcAttributeObjPk obj;
SilcPublicKey pk;
/* Request all attributes except PUBKEY */
attr = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
SILC_ATTRIBUTE_SERVICE,
SILC_ATTRIBUTE_STATUS_MOOD,
SILC_ATTRIBUTE_STATUS_FREETEXT,
SILC_ATTRIBUTE_STATUS_MESSAGE,
SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
SILC_ATTRIBUTE_PREFERRED_CONTACT,
SILC_ATTRIBUTE_TIMEZONE,
SILC_ATTRIBUTE_GEOLOCATION,
SILC_ATTRIBUTE_DEVICE_INFO, 0);
/* Load the Public Key */
if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_PEM))
if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_BIN)) {
print_out("", "-!- Couldn't load public key: %s", pubkey);
return;
}
obj.type = "silc-rsa";
obj.data = silc_pkcs_public_key_encode(pk, &obj.data_len);
attr = silc_attribute_payload_encode(attr,
SILC_ATTRIBUTE_USER_PUBLIC_KEY,
SILC_ATTRIBUTE_FLAG_VALID,
&obj, sizeof(obj));
silc_client_get_clients_whois(silc_client->client,silc_client->conn,
NULL, NULL, attr, add_pubkey_callback, pubkey);
/* Add a watch */
char *tmp=malloc(strlen(pubkey)+2);
sprintf(tmp, "+%s", pubkey);
silc_client_command_call(silc_client->client, silc_client->conn, NULL, "WATCH", "-add", tmp, NULL);
free(tmp);
}
void add_pubkey_callback(SilcClient client, SilcClientConnection conn,
SilcClientEntry *clients, SilcUInt32 clients_count,
void *context){
if (clients_count!=0) {
int i;
for (i=0; i<clients_count; i++){
add_buddy(clients[i]);
}
}
}
void init_buddylist() {
DIR *dir;
char *pubkey, *path;
struct dirent *entry;
path=malloc(strlen(getenv("HOME"))+40);
NULL_TEST(path);
sprintf(path, "%s/.silc/buddylist", (char *)getenv("HOME"));
create_dirtree(path);
dir=opendir(path);
while((entry=readdir(dir))) {
if(entry->d_name[0]=='.')
continue;
pubkey=malloc(strlen(path)+strlen(entry->d_name)+2);
NULL_TEST(pubkey);
sprintf(pubkey, "%s/%s", path, entry->d_name);
add_pubkey(pubkey);
free(pubkey);
}
closedir(dir);
free(path);
}
......@@ -38,7 +38,7 @@ si_process_mime(SilcClient client, SilcClientConnection conn,
SIMime simime = NULL;
Channel *c;
Query *q;
static char outfile[256], tmp[256];
static char outfile[1024], tmp[1024];
int ret;
if (!mime)
......@@ -113,7 +113,7 @@ si_process_mime(SilcClient client, SilcClientConnection conn,
/* Check if we support this MIME type */
for (simime = c->mimes; simime; simime = simime->next) {
const char *mtype = silc_mime_get_field(simime->mime, "Content-Type");
if (mtype && !strcmp(mtype, type))
if (!strcmp(mtype, type))
break;
}
if (!simime)
......@@ -133,7 +133,7 @@ si_process_mime(SilcClient client, SilcClientConnection conn,
/* Check if we support this MIME type */
for (simime = q->mimes; simime; simime = simime->next) {
const char *mtype = silc_mime_get_field(simime->mime, "Content-Type");
if (mtype && !strcmp(mtype, type))
if (!strcmp(mtype, type))
break;
}
if (!simime)
......@@ -149,11 +149,15 @@ si_process_mime(SilcClient client, SilcClientConnection conn,
}
if (simime->out_fd < 0) {
int flags = O_WRONLY;
/* Open FIFO for writing */
if (access(outfile, F_OK) == -1)
mkfifo(outfile, S_IRWXU);
simime->out_fd = open(outfile, O_WRONLY | O_NONBLOCK, 0);
if (simime->buffer == FALSE)
flags |= O_NONBLOCK;
simime->out_fd = open(outfile, flags, 0);
if (simime->out_fd < 0)
goto out;
}
......@@ -161,8 +165,13 @@ si_process_mime(SilcClient client, SilcClientConnection conn,
/* Write to FIFO */
while (data_len > 0) {
ret = write(simime->out_fd, data, data_len);
if (ret <= 0)
if (ret <= 0) {
if (errno == EPIPE) {
close(simime->out_fd);
simime->out_fd = -1;
}
break;
}
data += ret;
data_len -= ret;
}
......@@ -176,7 +185,7 @@ si_process_mime(SilcClient client, SilcClientConnection conn,
static int si_open_data_fifo(char *path, char *suffix, void *context)
{
char infile[256], tmp[32];
char infile[1024], tmp[32];
int fd;
memset(infile, 0, sizeof(infile));
......@@ -208,30 +217,32 @@ SILC_TASK_CALLBACK(si_handle_data_input)
SIMime simime = context;
Channel *c;
Query *q;
unsigned char buf[8192];
unsigned char buf[0xffff - 512];
unsigned char *data;
SilcUInt32 data_len;
int ret;
DEBUG("Start");
ret = read(fd, buf, sizeof(buf));
if (ret <= 0) {
/* Writer went away, close and reopen FIFO */
close(fd);
silc_schedule_unset_listen_fd(silc_client->client->schedule, fd);
silc_schedule_task_del_by_fd(silc_client->client->schedule, fd);
if (simime->type == CHANNEL) {
c = simime->context;
si_open_data_fifo(c->silc->channel_name,
(char *)silc_mime_get_field(simime->mime,
"Content-Type"),
context);
} else {
q = simime->context;
snprintf((char *)buf, sizeof(buf) - 1, "query/%s", q->silc->nickname);
si_open_data_fifo((char *)buf, (char *)silc_mime_get_field(simime->mime, "Content-Type"),
context);
if (errno == EPIPE) {
/* Writer went away, close and reopen FIFO */
close(fd);
silc_schedule_unset_listen_fd(silc_client->client->schedule, fd);
silc_schedule_task_del_by_fd(silc_client->client->schedule, fd);
if (simime->type == CHANNEL) {
c = simime->context;
si_open_data_fifo(c->silc->channel_name,
(char *)silc_mime_get_field(simime->mime,
"Content-Type"),
context);
} else {
q = simime->context;
snprintf((char *)buf, sizeof(buf) - 1, "query/%s", q->silc->nickname);
si_open_data_fifo((char *)buf, (char *)silc_mime_get_field(simime->mime,
"Content-Type"),
context);
}
}
return;
}
......@@ -263,13 +274,14 @@ SILC_TASK_CALLBACK(si_handle_data_input)
/* Open data FIFO for input */
static void si_open_mime(void *context, ContextType type, char *mimetype)
static void si_open_mime(void *context, ContextType type, char *mimetype,
bool buffer)
{
SIMime simime, mimes;
Channel *c;
Query *q;
int fd;
char path[256];
char path[1024];
memset(path, 0, sizeof(path));
if (type == CHANNEL) {
......@@ -282,13 +294,22 @@ static void si_open_mime(void *context, ContextType type, char *mimetype)
snprintf(path, sizeof(path) - 1, "query/%s", q->silc->nickname);
}
DEBUG("Input: MIME %s buffered=%s", mimetype, buffer ? "yes" : "no");
for (simime = mimes; simime; simime = simime->next) {
const char *mtype = silc_mime_get_field(simime->mime, "Content-Type");
if (mtype && !strcmp(mtype, mimetype))
return; /* already handled */
}
DEBUG("Input: MIME %s", mimetype);
if (!strcmp(mtype, mimetype)) {
if (simime->buffer != buffer && simime->out_fd != -1) {
close(simime->out_fd);
simime->out_fd = 1;
}
simime->buffer = buffer;
/* Already handled */
return;
}
}
simime = silc_calloc(1, sizeof(*simime));
if (!simime) {
......@@ -296,6 +317,7 @@ static void si_open_mime(void *context, ContextType type, char *mimetype)
return;
}
simime->out_fd = -1;
simime->buffer = buffer;
simime->type = type;
simime->context = context;
simime->mime = silc_mime_alloc();
......
......@@ -22,7 +22,7 @@
/* We like GNU :) */
#define _GNU_SOURCE
#define _GNU_SOURCE
#include <silcincludes.h> /* Mandatory include for SILC applications */
#include <silcclient.h> /* SILC Client Library API */
......@@ -31,7 +31,6 @@
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <getopt.h>
......@@ -81,12 +80,18 @@ typedef struct {
/* Mime context */
typedef struct SIMimeStruct {
int out_fd;
int buffer;
SilcMime mime;
ContextType type;
void *context;
struct SIMimeStruct *next;
} *SIMime;
typedef struct BuddyStruct {
SilcClientEntry client;
struct BuddyStruct *next;
} *Buddy;
typedef struct Channel Channel;
struct Channel {
int fd;
......@@ -122,10 +127,11 @@ char *realname = NULL;
char *host = "sauna.silcnet.org";
char *init_script=NULL;
int port=706;
char path[_POSIX_PATH_MAX];
char path[1024];
Channel *channels=NULL;
Query *queries=NULL;
Transfer *transfers=NULL;
Buddy buddies=NULL;
int debug=1;
int connected=0;
SilcClientOperations ops;
......@@ -170,6 +176,7 @@ silc_private_message(SilcClient client, SilcClientConnection conn,
/* All Copied Functions from ii */
#include "mit.c"
#include "mm.c"
#include "buddylist.c"
/* }}} */
/* {{{ Usage & Version*/
......@@ -494,24 +501,22 @@ void proc_channels_input(Channel *c, char *buf) {
/* MIME command */
else if (!strncmp("mime ", &buf[1], 5)) {
char *mtype;
mtype=&buf[4];
msg=strchr(mtype, ' ');
if (!msg) {
print_out(c->silc->channel_name, "-!- Error: /mime <mimetype>");
return;
}
msg[0]=0;
if(!++msg){
print_out(c->silc->channel_name, "-!- Error: /mime <mimetype>");
int i, b = FALSE;
char **argv;
SilcUInt32 *argv_lens, *argv_types, argc;
silc_parse_command_line((unsigned char *)buf,
(void *)&argv, &argv_lens,
&argv_types, &argc, 4);
if (argc < 2) {
print_out(c->silc->channel_name, "-!- Error: /mime <mimetype> [-buffer]");
return;
}
if(!msg || ! strlen(msg)){
print_out(c->silc->channel_name, "-!- Error: /mime <mimetype>");
return;
for (i = 2; i < argc; i++) {
if (!strcmp("-buffer", argv[i]))
b = TRUE;
}
si_open_mime(c, CHANNEL, msg);
si_open_mime(c, CHANNEL, argv[1], b);
return;
}
......@@ -567,24 +572,22 @@ void proc_queries_input (Query *peer, char *buf ) {
/* MIME command */
else if (!strncmp("mime ", &buf[1], 5)) {
char *mtype;
mtype=&buf[4];
msg=strchr(mtype, ' ');
if (!msg) {
print_out(path, "-!- Error: /mime <mimetype>");
int i, b = FALSE;
char **argv;
SilcUInt32 *argv_lens, *argv_types, argc;
silc_parse_command_line((unsigned char *)buf,
(void *)&argv, &argv_lens,
&argv_types, &argc, 4);
if (argc < 2) {
print_out(path, "-!- Error: /mime <mimetype> [-buffer]");
return;
}
msg[0]=0;
if(!++msg){
print_out(path, "-!- Error: /mime <mimetype>");
return;
}
if(!msg || ! strlen(msg)){
print_out(path, "-!- Error: /mime <mimetype>");
return;
for (i = 2; i < argc; i++) {
if (!strcmp("-buffer", argv[i]))
b = TRUE;
}
si_open_mime(peer, QUERY, msg);
si_open_mime(peer, QUERY, argv[1], b);
return;
}
......@@ -614,15 +617,19 @@ void proc_watch(SilcClientEntry client, SilcUInt32 mode, SilcNotifyType type){
free(str);
break;
case SILC_NOTIFY_TYPE_KILLED:
rm_buddy(client);
print_out("", "-!- Watch: %s was killed from the network", client->nickname);
break;
case SILC_NOTIFY_TYPE_SIGNOFF:
rm_buddy(client);
print_out("", "-!- Watch: %s quit from network", client->nickname);
break;
case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
rm_buddy(client);
print_out("", "-!- Watch: %s was quit from network trough a server signoff", client->nickname);
break;
case SILC_NOTIFY_TYPE_NONE:
add_buddy(client);
print_out("", "-!- Watch: %s is online now", client->nickname);
break;
default:
......@@ -634,34 +641,34 @@ void proc_watch(SilcClientEntry client, SilcUInt32 mode, SilcNotifyType type){
/* {{{ print_out */
static void print_out(char *channel, char *buf, ...)
{
static char outfile[256];
FILE *out;
static char buft[8];
time_t t = time(0);
char *tmp;
char *msg;
va_list va;
va_start(va, buf);
create_filepath(outfile, sizeof(outfile), channel, "out");
out = fopen(outfile, "a");
static char outfile[256];
FILE *out;
static char buft[8];
time_t t = time(0);
char *tmp;
char *msg;
va_list va;
va_start(va, buf);
create_filepath(outfile, sizeof(outfile), channel, "out");
out = fopen(outfile, "a");
#ifndef _GNU_SOURCE
tmp=malloc(4097);
NULL_TEST(tmp);
/* Outputstring */
vsnprintf(tmp, 4096, buf, va);
tmp=malloc(4097);
NULL_TEST(tmp);
/* Outputstring */
vsnprintf(tmp, 4096, buf, va);
#else
vasprintf(&tmp, buf, va);
#endif
Utf8ToLocal(tmp, &msg);
strftime(buft, sizeof(buft), "%R ", localtime(&t));
/* Output */
fprintf(out, "%s%s\n",buft, msg);
fclose(out);
free(msg);
free(tmp);
va_end(va);
vasprintf(&tmp, buf, va);
#endif
Utf8ToLocal(tmp, &msg);
strftime(buft, sizeof(buft), "%R ", localtime(&t));
/* Output */
fprintf(out, "%s%s\n",buft, msg);
fclose(out);
free(msg);
free(tmp);
va_end(va);
}
/* }}} */
/* {{{ get_scc_name_by_id ( Server, Channel, Client )*/
......@@ -1094,6 +1101,8 @@ int run(void)
}
}
}
/* Init the Buddylist */
init_buddylist();
for (;;) {
run_once();
......@@ -2033,7 +2042,7 @@ int main(int argc, char **argv)
default: usage(); break;
}
}
if(!strlen(prefix)){
if(!strlen(prefix)){
prefix=malloc(strlen(getenv("HOME"))+5);
NULL_TEST_ARG(prefix,1);
sprintf(prefix, "%s/irc", getenv("HOME"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment