1 #ifndef _AmMimeBody_h_
2 #define _AmMimeBody_h_
3 
4 #include "AmArg.h"
5 
6 #include <string>
7 #include <list>
8 #include <map>
9 
10 using std::string;
11 using std::list;
12 using std::map;
13 
14 struct AmContentType
15 {
16   struct Param
17   {
18 
19     enum Type {
20       UNPARSED=0,
21       BOUNDARY,
22       OTHER
23     };
24 
25     Type   type;
26     string name;
27     string value;
28 
29     Param(const string& name, const string& value)
30       : type(UNPARSED), name(name), value(value) {}
31 
32     int parseType();
33   };
34 
35   typedef list<Param*> Params;
36 
37   string type;
38   string subtype;
39   Params params;
40   Param* mp_boundary;
41 
42   AmContentType();
43   AmContentType(const AmContentType& ct);
44   ~AmContentType();
45 
46   const AmContentType& operator = (const AmContentType& r_ct);
47 
48   int  parse(const string& ct);
49   int  parseParams(const char* c, const char* end);
50 
51   void setType(const string& t);
52   void setSubType(const string& st);
53 
54   bool isType(const string& t) const;
55   bool isSubType(const string& st) const;
56   bool hasContentType(const string& content_type) const;
57 
58   /** get content-type without any parameters */
59   string getStr() const;
60 
61   /** get content-type with parameters */
62   string getHdr() const;
63 
64   /** Clear and free param list */
65   void clearParams();
66 
67   /** set a random boundary string */
68   void resetBoundary();
69 };
70 
71 class AmMimeBody
72 : public AmObject
73 {
74 public:
75   typedef list<AmMimeBody*>  Parts;
76 
77 private:
78   AmContentType  ct;
79   string         hdrs;
80   unsigned int   content_len;
81   unsigned char* payload;
82 
83   Parts parts;
84 
85   void clearParts();
86   void clearPart(Parts::iterator position);
87   void clearPayload();
88 
89   int parseMultipart(const unsigned char* buf, unsigned int len);
90   int findNextBoundary(unsigned char** beg, unsigned char** end);
91   int parseSinglePart(unsigned char* buf, unsigned int len);
92 
93   void convertToMultipart();
94   void convertToSinglepart();
95 
96 public:
97   /** Empty constructor */
98   AmMimeBody();
99 
100   /** Deep-copy constructor */
101   AmMimeBody(const AmMimeBody& body);
102 
103   /** Destuctor */
104   ~AmMimeBody();
105 
106   /** Deep copy operator */
107   const AmMimeBody& operator = (const AmMimeBody& r_body);
108 
109   /** Parse a body (single & multi-part) */
110   int  parse(const string& content_type,
111 	     const unsigned char* buf,
112 	     unsigned int len);
113 
114   /** Set the payload of this body */
115   void setPayload(const unsigned char* buf, unsigned int len);
116 
117   /** Set part headers (intended for sub-parts)*/
118   void setHeaders(const string& hdrs);
119 
120   /**
121    * Add a new part to this body, possibly
122    * converting to multi-part if necessary.
123    * @return a pointer to the new empty part.
124    */
125   AmMimeBody* addPart(const string& content_type);
126 
127   /**
128    * Delete a body part, converting resulting body to single-part if necessary.
129    */
130   int deletePart(const string& content_type);
131 
132   /** Get content-type without any parameters */
133   string getCTStr() const { return ct.getStr(); }
134 
135   /** Get content-type with parameters */
136   string getCTHdr() const { return ct.getHdr(); }
137 
138   /** @return the list of sub-parts */
139   const Parts& getParts() const { return parts; }
140 
141   /** @return the sub-part headers */
142   const string& getHeaders() const { return hdrs; }
143 
144   /**
145    * @return a pointer to the payload of this part.
146    *         in case of multi-part, NULL is returned.
147    */
148   const unsigned char* getPayload() const { return payload; }
149 
150   /**
151    * @return the payload length of this part.
152    *         in case of multi-part, 0 is returned.
153    */
154   unsigned int   getLen() const { return content_len; }
155 
156   /** @return true if no payload assigned and no sub-parts available */
157   bool empty() const;
158 
159   /** @return true if this part has the provided content-type */
160   bool isContentType(const string& content_type) const;
161 
162   /**
163    * @return a pointer to a part of the coresponding
164    *         content-type (if available).
165    *         This could be a pointer to this body.
166    */
167   AmMimeBody* hasContentType(const string& content_type);
168 
169   /**
170    * @return a const pointer to a part of the coresponding
171    *         content-type (if available).
172    *         This could be a pointer to this body.
173    */
174   const AmMimeBody* hasContentType(const string& content_type) const;
175 
176   /**
177    * Print the body including sub-parts suitable for sending
178    * within the body of a SIP message.
179    */
180   void print(string& buf) const;
181 
182   const AmContentType &getContentType() { return ct; }
183   void setContentType(const AmContentType &_ct) { ct = _ct; }
184   void addPart(const AmMimeBody &part) { parts.push_back(new AmMimeBody(part)); }
185 };
186 
187 #endif
188