addy_book.c
上传用户:knt0001
上传日期:2022-01-28
资源大小:264k
文件大小:9k
源码类别:

Email客户端

开发平台:

C/C++

  1. /**
  2.     eMail is a command line SMTP client.
  3.     Copyright (C) 2001 - 2008 email by Dean Jones
  4.     Software supplied and written by http://www.cleancode.org
  5.     This file is part of eMail.
  6.     eMail is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.     eMail is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.     You should have received a copy of the GNU General Public License
  15.     along with eMail; if not, write to the Free Software
  16.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. **/
  18. #if HAVE_CONFIG_H
  19. # include "config.h"
  20. #endif
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "email.h"
  25. #include "addr_parse.h"
  26. #include "utils.h"
  27. #include "addy_book.h"
  28. #include "error.h"
  29. /*
  30.  * Entry is a structure in which we will hold a parsed
  31.  * string from the address book.  
  32.  * 
  33.  * e_gors == "group" for group "single" for single and NULL for neither
  34.  * e_name == Name of entry
  35.  * e_addr == Addresses found with entry 
  36.  *
  37.  */
  38. typedef struct {
  39. char *e_gors;
  40. char *e_name;
  41. char *e_addr;
  42. } ENTRY;
  43. /**
  44.  * Frees an ENTRY structure if it needs to be feed 
  45. **/
  46. static void
  47. freeEntry(ENTRY *en)
  48. {
  49. xfree(en->e_gors);
  50. xfree(en->e_name);
  51. xfree(en->e_addr);
  52. }
  53. static void
  54. separateDestr(void *ptr)
  55. {
  56. xfree(ptr);
  57. }
  58. static void
  59. addrDestr(void *ptr)
  60. {
  61. struct addr *a = (struct addr *)ptr;
  62. if (a) {
  63. xfree(a->name);
  64. xfree(a->email);
  65. xfree(a);
  66. }
  67. }
  68. /** 
  69.  * Seperate will take a string of command separated fields
  70.  * and with separate them into a linked list for return 
  71.  * by the function.
  72. **/
  73. static dlist
  74. separate(char *string)
  75. {
  76. char *next;
  77. int counter;
  78. dlist ret = dlInit(separateDestr);
  79. counter = 0;
  80. next = strtok(string, ",");
  81. while (next) {
  82. /* don't let our counter get over 99 address' */
  83. if (counter == 99) {
  84. break;
  85. }
  86. /**
  87.  * make sure that next isn't too large, if it is, don't store it
  88.  * get next element and move on...
  89.  */
  90. if (strlen(next) > MAXBUF) {
  91. next = strtok(NULL, ",");
  92. continue;
  93. }
  94. /* Get rid of white spaces */
  95. while (*next == ' ' || *next == 't') {
  96. next++;
  97. }
  98. dlInsertTop(ret, xstrdup(next));
  99. next = strtok(NULL, ",");
  100. counter++;
  101. }
  102. return ret;
  103. }
  104. /**
  105.  * Makes sure that all values are available for storage in
  106.  * the ENTRY structure.  
  107.  *
  108.  * If NONE of the values are ready, it returns -1 to let 
  109.  * the caller know that this is not an ERROR and should 
  110.  * continue.
  111.  *
  112.  * If some of the values aren't available, something fishy
  113.  * went on and we'll return ERROR
  114.  *
  115.  * Otherwise, store the values in the ENTRY struct.
  116. **/
  117. static int
  118. makeEntry(ENTRY *en, const char *gors, const char *name, const char *addr)
  119. {
  120. if ((*gors == '') && (*name == '') && (*addr == '')) {
  121. return -1;            /* No error */
  122. }
  123. if ((*gors == '') || (*name == '') || (*addr == '')) {
  124. return ERROR;
  125. }
  126. en->e_gors = xstrdup(gors);
  127. en->e_name = xstrdup(name);
  128. en->e_addr = xstrdup(addr);
  129. return 0;
  130. }
  131. /**
  132.  * Parses the address book file in search of the correct
  133.  * entry.  If the entry desired is found, then it is stored
  134.  * in the ENTRY structure that is passed.
  135. **/
  136. static int
  137. getEntry(ENTRY *en, char *ent, FILE *book)
  138. {
  139. int ch, line=1;
  140. dstrbuf *ptr, *gors;
  141. dstrbuf *name, *addr;
  142. assert(book != NULL);
  143. rewind(book); /* start at top of file */
  144. gors = DSB_NEW;
  145. name = DSB_NEW;
  146. addr = DSB_NEW;
  147. ptr = gors;
  148. en->e_gors = en->e_name = en->e_addr = NULL;
  149. while ((ch = fgetc(book)) != EOF) {
  150. switch (ch) {
  151. case '#':
  152. while ((ch = fgetc(book)) != 'n')
  153. ;
  154. break;
  155. case '\':
  156. ch = fgetc(book);
  157. if (ch == 'r') {
  158. ch = fgetc(book);
  159. }
  160. if (ch != 'n') {
  161. dsbCatChar(ptr, ch);
  162. }
  163. line++;
  164. ch = 0;
  165. break;
  166. case ''':
  167. if (copyUpTo(ptr, ch, book) == 'n') {
  168. ch = line;
  169. goto exit;
  170. }
  171. break;
  172. case '"':
  173. if (copyUpTo(ptr, ch, book) == 'n') {
  174. ch = line;
  175. goto exit;
  176. }
  177. break;
  178. case ':':
  179. if (name->len != 0) {
  180. ch = line;
  181. goto exit;
  182. }
  183. ptr = name;
  184. break;
  185. case '=':
  186. if (addr->len != 0) {
  187. ch = line;
  188. goto exit;
  189. }
  190. ptr = addr;
  191. break;
  192. case ' ':
  193. /* Nothing for spaces */
  194. break;
  195. case 't':
  196. /* Nothing for tabs */
  197. break;
  198. case 'r':
  199. /* Ignore */
  200. break;
  201. case 'n':
  202. /* Handle newlines below */
  203. break;
  204. default:
  205. dsbCatChar(ptr, ch);
  206. break;
  207. }
  208. if (ch == 'n') {
  209. if (strcasecmp(name->str, ent) == 0) {
  210. if (makeEntry(en, gors->str, name->str, addr->str) 
  211. == ERROR) {
  212. ch = line;
  213. goto exit;
  214. }
  215. ch = 0;
  216. goto exit;
  217. }
  218. /* Let's keep looking ! */
  219. dsbDestroy(gors);
  220. dsbDestroy(name);
  221. dsbDestroy(addr);
  222. gors = DSB_NEW;
  223. name = DSB_NEW;
  224. addr = DSB_NEW;
  225. ptr = gors;
  226. line++;
  227. }
  228. }
  229. exit:
  230. dsbDestroy(gors);
  231. dsbDestroy(name);
  232. dsbDestroy(addr);
  233. /* Possible EOF or Line number */
  234. return ch;
  235. }
  236. /**
  237.  * Add an email to the list.  Make sure it is formated properly.
  238.  * After formated properly, list_insert() it 
  239. **/
  240. static void
  241. insertEntry(dlist to, const char *name, const char *addr)
  242. {
  243. struct addr *newaddr = xmalloc(sizeof(struct addr));
  244. if (validateEmail(addr) == ERROR) {
  245. warning("Email address '%s' is invalid. Skipping...n", addr);
  246. return;
  247. }
  248. if (*name != '' && strcmp(name, "") != 0) { 
  249. newaddr->name = xstrdup(name);
  250. }
  251. newaddr->email = xstrdup(addr);
  252. dlInsertTop(to, newaddr);
  253. }
  254. /**
  255.  * A wrapper for insertEntry for when we seem to have just an address 
  256.  * (ie not an address book entry.)
  257.  */
  258. static void
  259. insertAddrEntry(dlist to, const char *addr)
  260. {
  261. dstrbuf *name = DSB_NEW;
  262. dstrbuf *email = DSB_NEW;
  263. if (parseAddr(addr, name, email) == ERROR) {
  264. warning("Email address %s is incorrectly formatted. Skipping...n", addr);
  265. } else {
  266. char *stripped = stripEmailName(name->str);
  267. insertEntry(to, stripped, email->str);
  268. }
  269. dsbDestroy(name);
  270. dsbDestroy(email);
  271. }
  272. /**
  273.  * This function checks each address in tmp and formats it
  274.  * properly and copies it over to the new list.
  275. **/
  276. static void
  277. checkAndCopy(dlist to, dlist from)
  278. {
  279. char *next=NULL;
  280. while ((next=(char *)dlGetNext(from)) != NULL) {
  281. insertAddrEntry(to, next);
  282. }
  283. }
  284. static int addEntry(dlist to, ENTRY *en, FILE *book);
  285. /**
  286.  * Loops through the linked list and calls Get_entry for
  287.  * each name in the linked list.  It will add each entry into
  288.  * the 'to' linked lists when an appropriate match is found
  289.  * from the address book.
  290. **/
  291. static int
  292. checkAddrBook(dlist to, dlist from, FILE *book)
  293. {
  294. ENTRY en;
  295. int retval;
  296. char *next=NULL;
  297. /* Go through list from, resolving to list curr */
  298. while ((next=(char *)dlGetNext(from)) != NULL) {
  299. retval = getEntry(&en, next, book);
  300. if (retval > 0) {
  301. fatal("Address book incorrectly formated on line %dn", retval);
  302. return ERROR;
  303. } else if (retval == EOF) {
  304. insertAddrEntry(to, next);
  305. } else {
  306. if (addEntry(to, &en, book) == ERROR) {
  307. return ERROR;
  308. }
  309. }
  310. freeEntry(&en);
  311. }
  312. return SUCCESS; 
  313. }
  314. /**
  315.  * Add an entry to the linked lists.
  316.  * If entry is a group, we must separate the people inside of 
  317.  * the group and re-call check_addr_book for those entries.
  318. **/
  319. static int
  320. storeGroup(dlist to, ENTRY *en, FILE *book)
  321. {
  322. static int set_group;
  323. dlist tmp=NULL;
  324. if (set_group) {
  325. fatal("You can't define groups within groups!n");
  326. return ERROR;
  327. }
  328. tmp = separate(en->e_addr);
  329. set_group = 1;
  330. checkAddrBook(to, tmp, book);
  331. set_group = 0;
  332. dlDestroy(tmp);
  333. return 0;
  334. }
  335. /**
  336.  * Wrapper for adding an entry.  Will call Store_group
  337.  * or Store_single, or Store_email if the entry is 
  338.  * one of the above.
  339. **/
  340. static int
  341. addEntry(dlist to, ENTRY *en, FILE *book)
  342. {
  343. if (strcmp(en->e_gors, "group") == 0) {
  344. if (storeGroup(to, en, book) == ERROR) {
  345. return ERROR;
  346. }
  347. } else {
  348. insertEntry(to, en->e_name, en->e_addr);
  349. }
  350. return 0;
  351. }
  352. /** 
  353.  * GetNames just calls the correct functions to 
  354.  * split up the names passed to email and check
  355.  * them against the address book and it will return 
  356.  * a linked list 'list_t' with the correct separate names.
  357. **/
  358. dlist
  359. getNames(char *string)
  360. {
  361. FILE *book;
  362. char *addr_book;
  363. dlist tmp = NULL;
  364. dstrbuf *bpath=NULL;
  365. dlist ret = dlInit(addrDestr);
  366. addr_book = getConfValue("ADDRESS_BOOK");
  367. /* Read in and hash the address book */
  368. if (!(tmp = separate(string))) {
  369. return NULL;
  370. }
  371. if (!addr_book) {
  372. checkAndCopy(ret, tmp);
  373. } else {
  374. bpath = expandPath(addr_book);
  375. book = fopen(bpath->str, "r");
  376. if (!book) {
  377. fatal("Can't open address book: '%s'n", bpath->str);
  378. dlDestroy(ret);
  379. dlDestroy(tmp);
  380. dsbDestroy(bpath);
  381. return NULL;
  382. }
  383. dsbDestroy(bpath);
  384. checkAddrBook(ret, tmp, book);
  385. fclose(book);
  386. }
  387. dlDestroy(tmp);
  388. return ret;
  389. }