*/
#define VCARD_EXT_FORMAT "Citadel vCard: personal card for %s at %s"
+/*
+ * Citadel will accept either text/vcard or text/x-vcard as the MIME type
+ * for a vCard. The following definition determines which one it *generates*
+ * when serializing.
+ */
+#define VCARD_MIME_TYPE "text/x-vcard"
#include "sysdep.h"
#include <stdlib.h>
#include <limits.h>
#include "citadel.h"
#include "server.h"
-#include "sysdep_decls.h"
#include "citserver.h"
#include "support.h"
#include "config.h"
#include "control.h"
-#include "serv_extensions.h"
#include "room_ops.h"
#include "user_ops.h"
#include "policy.h"
#include "serv_ldap.h"
#include "serv_vcard.h"
+
+#include "ctdl_module.h"
+
+
+
/*
* set global flag calling for an aide to validate new users
*/
*/
void extract_inet_email_addrs(char *emailaddrbuf, size_t emailaddrbuf_len,
char *secemailaddrbuf, size_t secemailaddrbuf_len,
- struct vCard *v) {
+ struct vCard *v, int local_addrs_only) {
char *s, *addr;
int instance = 0;
int saved_instance = 0;
addr = strdup(s);
striplt(addr);
if (strlen(addr) > 0) {
- if (IsDirectory(addr)) {
+ if ( (IsDirectory(addr, 1)) ||
+ (!local_addrs_only) ) {
++saved_instance;
if ((saved_instance == 1) && (emailaddrbuf != NULL)) {
safestrncpy(emailaddrbuf, addr, emailaddrbuf_len);
if (ser != NULL) {
msg->cm_fields['M'] = realloc(msg->cm_fields['M'], strlen(ser) + 1024);
sprintf(msg->cm_fields['M'],
- "Content-type: text/vcard"
+ "Content-type: " VCARD_MIME_TYPE
"\r\n\r\n%s\r\n", ser);
free(ser);
}
v = vcard_load(msg->cm_fields['M']);
extract_inet_email_addrs(CC->cs_inet_email, sizeof CC->cs_inet_email,
CC->cs_inet_other_emails, sizeof CC->cs_inet_other_emails,
- v);
+ v, 1);
extract_friendly_name(CC->cs_inet_fn, sizeof CC->cs_inet_fn, v);
vcard_free(v);
* is going to notice what we're trying to do, and delete the old vCard.
*/
CtdlWriteObject(USERCONFIGROOM, /* which room */
- "text/vcard", /* MIME type */
+ VCARD_MIME_TYPE,/* MIME type */
temp, /* temp file */
u, /* which user */
0, /* not binary */
extract_token(buf, adr, 6, ';', sizeof buf);
cprintf("%s\n", buf); /* country */
cprintf("000\n");
+ vcard_free(v);
}
}
+
+
+/*
+ * Callback function for cmd_dvca() that hunts for vCard content types
+ * and outputs any email addresses found within.
+ */
+void dvca_mime_callback(char *name, char *filename, char *partnum, char *disp,
+ void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
+ void *cbuserdata) {
+
+ struct vCard *v;
+ char displayname[256];
+ int displayname_len;
+ char emailaddr[256];
+ int i;
+ int has_commas = 0;
+
+ if ( (strcasecmp(cbtype, "text/vcard")) && (strcasecmp(cbtype, "text/x-vcard")) ) {
+ return;
+ }
+
+ v = vcard_load(content);
+ if (v == NULL) return;
+
+ extract_friendly_name(displayname, sizeof displayname, v);
+ extract_inet_email_addrs(emailaddr, sizeof emailaddr, NULL, 0, v, 0);
+
+ displayname_len = strlen(displayname);
+ for (i=0; i<displayname_len; ++i) {
+ if (displayname[i] == '\"') displayname[i] = ' ';
+ if (displayname[i] == ';') displayname[i] = ',';
+ if (displayname[i] == ',') has_commas = 1;
+ }
+ striplt(displayname);
+
+ cprintf("%s%s%s <%s>\n",
+ (has_commas ? "\"" : ""),
+ displayname,
+ (has_commas ? "\"" : ""),
+ emailaddr
+ );
+
+ vcard_free(v);
+}
+
+
+/*
+ * Back end callback function for cmd_dvca()
+ *
+ * It's basically just passed a list of message numbers, which we're going
+ * to fetch off the disk and then pass along to the MIME parser via another
+ * layer of callback...
+ */
+void dvca_callback(long msgnum, void *userdata) {
+ struct CtdlMessage *msg = NULL;
+
+ msg = CtdlFetchMessage(msgnum, 1);
+ if (msg == NULL) return;
+ mime_parser(msg->cm_fields['M'],
+ NULL,
+ *dvca_mime_callback, /* callback function */
+ NULL, NULL,
+ NULL, /* user data */
+ 0
+ );
+ CtdlFreeMessage(msg);
+}
+
+
+/*
+ * Dump VCard Addresses
+ */
+void cmd_dvca(char *argbuf)
+{
+ if (CtdlAccessCheck(ac_logged_in)) return;
+
+ cprintf("%d addresses:\n", LISTING_FOLLOWS);
+ CtdlForEachMessage(MSGS_ALL, 0, NULL, NULL, NULL, dvca_callback, NULL);
+ cprintf("000\n");
+}
+
+
/*
* Query Directory
*/
v = vcard_get_user(&CC->user);
extract_inet_email_addrs(CC->cs_inet_email, sizeof CC->cs_inet_email,
CC->cs_inet_other_emails, sizeof CC->cs_inet_other_emails,
- v);
+ v, 1);
extract_friendly_name(CC->cs_inet_fn, sizeof CC->cs_inet_fn, v);
vcard_free(v);
if (ser != NULL) {
vmsg->cm_fields['M'] = malloc(strlen(ser) + 1024);
sprintf(vmsg->cm_fields['M'],
- "Content-type: text/vcard"
+ "Content-type: " VCARD_MIME_TYPE
"\r\n\r\n%s\r\n", ser);
free(ser);
}
}
-char *serv_postfix_tcpdict(void)
-{
- CtdlRegisterServiceHook(config.c_pftcpdict_port, /* Postfix */
- NULL,
- check_get_greeting,
- check_get,
- NULL);
- return "$Id$";
-}
-
-char *serv_vcard_init(void)
+CTDL_MODULE_INIT(vcard)
{
struct ctdlroom qr;
char filename[256];
CtdlRegisterProtoHook(cmd_qdir, "QDIR", "Query Directory");
CtdlRegisterProtoHook(cmd_gvsn, "GVSN", "Get Valid Screen Names");
CtdlRegisterProtoHook(cmd_gvea, "GVEA", "Get Valid Email Addresses");
+ CtdlRegisterProtoHook(cmd_dvca, "DVCA", "Dump VCard Addresses");
CtdlRegisterUserHook(vcard_newuser, EVT_NEWUSER);
CtdlRegisterUserHook(vcard_purge, EVT_PURGEUSER);
CtdlRegisterNetprocHook(vcard_extract_from_network);
chown(filename, CTDLUID, (-1));
}
+ /* for postfix tcpdict */
+ CtdlRegisterServiceHook(config.c_pftcpdict_port, /* Postfix */
+ NULL,
+ check_get_greeting,
+ check_get,
+ NULL);
+
+ /* return our Subversion id for the Log */
return "$Id$";
}