Annotation of parser3/src/classes/mail.C, revision 1.2
1.1 paf 1: /** @file
2: Parser: @b mail parser class.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
5:
6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
7:
1.2 ! paf 8: $Id: mail.C,v 1.1 2001/04/07 10:34:39 paf Exp $
1.1 paf 9: */
10:
11: #include "pa_config_includes.h"
12:
13: #include "_mail.h"
14: #include "pa_common.h"
15: #include "pa_request.h"
16:
17: // global var
18:
19: VStateless_class *mail_class;
20:
1.2 ! paf 21: // consts
! 22:
1.1 paf 23: // methods
24:
25: struct Mail_info {
26: String *attribute_to_exclude;
27: String *header;
1.2 ! paf 28: const String **from, **to;
1.1 paf 29: };
30:
31: static void add_header_attribute(const Hash::Key& aattribute, Hash::Val *ameaning,
32: void *info) {
33:
34: Value& lmeaning=*static_cast<Value *>(ameaning);
35: Mail_info& mi=*static_cast<Mail_info *>(info);
1.2 ! paf 36:
! 37: // exclude one attribute [body]
1.1 paf 38: if(aattribute==*mi.attribute_to_exclude)
39: return;
40:
1.2 ! paf 41: // fetch from & to from header for SMTP
! 42: if(mi.from && aattribute=="from")
! 43: *mi.from=&lmeaning.as_string();
! 44: if(mi.to && aattribute=="to")
! 45: *mi.to=&lmeaning.as_string();
! 46:
! 47: // append header line
! 48: *mi.header+=aattribute;
! 49: *mi.header+=":";
! 50: *mi.header+=attributed_meaning_to_string(lmeaning, String::UL_MAIL_HEADER);
! 51: *mi.header+="\n";
! 52: }
! 53: struct Seq_item {
! 54: const String *part_number;
! 55: Value *part_value;
! 56: };
! 57: static void add_part(const Hash::Key& part_number, Hash::Val *part_value,
! 58: void *info) {
! 59: Seq_item **seq_ref=static_cast<Seq_item **>(info);
! 60: (**seq_ref).part_number=&part_number;
! 61: (**seq_ref).part_value=static_cast<Value *>(part_value);
! 62: (*seq_ref)++;
! 63: }
! 64: static double key_of_part(const void *item) {
! 65: const char *cstr=static_cast<const Seq_item *>(item)->part_number->cstr();
! 66: char *error_pos;
! 67: return strtod(cstr, &error_pos);
! 68: }
! 69: static int sort_cmp_string_double_value(const void *a, const void *b) {
! 70: double va=key_of_part(a);
! 71: double vb=key_of_part(b);
! 72: if(va<vb)
! 73: return -1;
! 74: else if(va>vb)
! 75: return +1;
! 76: else
! 77: return 0;
1.1 paf 78: }
1.2 ! paf 79: static const String& letter_hash_to_string(Request& r, const String& method_name,
! 80: Hash& letter_hash, int level,
! 81: const String **from, const String **to) {
! 82: Pool& pool=r.pool();
! 83:
! 84: // prepare header: 'hash' without "body"
! 85: String& result=*new(pool) String(pool);
! 86: Mail_info mail_info={
! 87: /*excluding*/ body_name,
! 88: &result,
! 89: from, to
! 90: };
! 91: letter_hash.for_each(add_header_attribute, &mail_info);
! 92:
! 93: if(Value *body_element=static_cast<Value *>(letter_hash.get(*body_name))) {
! 94: if(Hash *body_hash=body_element->get_hash()) {
! 95: char *boundary=(char *)pool.malloc(MAX_NUMBER);
! 96: snprintf(boundary, MAX_NUMBER, "B%d", level);
! 97: // multi-part
! 98: result+="content-type: multipart/mixed;\n"
! 99: " boundary=\"----="; result+=boundary; result+="\"\n"
! 100: "\n"
! 101: "This is a multi-part message in MIME format.";
! 102:
! 103: // body parts
! 104: // collect
! 105: Seq_item *seq=(Seq_item *)malloc(sizeof(Seq_item)*body_hash->size());
! 106: Seq_item *seq_ref=seq; body_hash->for_each(add_part, &seq_ref);
! 107: // sort
! 108: _qsort(seq, body_hash->size(), sizeof(Seq_item),
! 109: sort_cmp_string_double_value);
! 110: // insert parts in 'seq' order
! 111: for(int i=0; i<body_hash->size(); i++) {
! 112: // intermediate boundary
! 113: result+="\n------="; result+=boundary; result+="\n";
! 114:
! 115: if(Hash *part_hash=seq[i].part_value->get_hash())
! 116: result+=letter_hash_to_string(r, method_name, *part_hash,
! 117: level+1, 0, 0);
! 118: else
! 119: PTHROW(0, 0,
! 120: seq[i].part_number,
! 121: "part is not hash");
! 122: }
! 123:
! 124: // finish boundary
! 125: result+="\n------="; result+=boundary; result+="--\n";
! 126: } else {
! 127: result+="\n"; // header|body separator
! 128: result+=body_element->as_string();
! 129: }
! 130: } else
! 131: PTHROW(0, 0,
! 132: &method_name,
! 133: "has no $body");
! 134:
! 135: return result;
! 136: }
! 137:
1.1 paf 138: static void _send(Request& r, const String& method_name, Array *params) {
139: Pool& pool=r.pool();
140:
141: Value& vhash=*static_cast<Value *>(params->get(0));
142: // forcing [this body type]
143: r.fail_if_junction_(true, vhash, method_name, "message must not be code");
144:
145: Hash *hash=vhash.get_hash();
146: if(!hash)
147: PTHROW(0, 0,
148: &method_name,
149: "message must be hash");
150:
1.2 ! paf 151: const String *from, *to;
! 152: const String& string=letter_hash_to_string(r, method_name, *hash, 0, &from, &to);
1.1 paf 153:
1.2 ! paf 154: r.write_assign_lang(*new(pool) VString(string));
1.1 paf 155: }
156:
157: // initialize
158: void initialize_mail_class(Pool& pool, VStateless_class& vclass) {
159: // ^mail:send{hash}
160: vclass.add_native_method("send", Method::CT_STATIC, _send, 1, 1);
161: }
E-mail: