server: intialize aux_header buffer to null if the data is missing.
[tridge/openchange.git] / branches / plugfest / libmapi++ / property_container.h
1 /*
2    libmapi C++ Wrapper
3    Property Tag Container Class
4
5    Copyright (C) Alan Alvarez 2008.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifndef LIBMAPIPP__PROPERTY_CONTAINER_H__
22 #define LIBMAPIPP__PROPERTY_CONTAINER_H__
23
24 #include <stdint.h>
25 #include <iostream> // for debugging only.
26
27 #include <libmapi++/clibmapi.h>
28 #include <libmapi++/mapi_exception.h>
29
30 // This is not declared in any of libmapi's headers, but it is defined in libmapi/property.c
31 extern "C" {
32 extern const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp);
33 }
34
35 namespace libmapipp
36 {
37 /// Iterator to use with Property Container
38 class property_container_iterator {
39         public:
40                 /// Default Constructor. Creates an invalid iterator.
41                 property_container_iterator() : m_property_values(NULL), m_mapi_property_values(NULL)
42                 {}
43
44                 property_container_iterator(SPropValue* property_values) : m_property_values(property_values),
45                                                                            m_mapi_property_values(NULL)
46                 {}
47
48                 property_container_iterator(mapi_SPropValue* mapi_property_values) : m_property_values(NULL),
49                                                                                      m_mapi_property_values(mapi_property_values)
50                 {}
51
52                 /** \brief Get Property Tag Type.
53                  *  \return Type of property this iterator points to or MAPI_PROP_RESERVED if this is an invalid iterator.
54                  *  Valid Types are: 
55                  *  - PT_BOOLEAN 
56                  *  - PT_I2 
57                  *  - PT_LONG 
58                  *  - PT_DOUBLE 
59                  *  - PT_I8 
60                  *  - PT_SYSTIME 
61                  *  - PT_ERROR 
62                  *  - PT_STRING8 
63                  *  - PT_UNICODE 
64                  *  - PT_BINARY
65                  *  - PT_CLSID
66                  *  - PT_ERROR
67                  *  - PT_MV_SHORT
68                  *  - PT_MV_LONG
69                  *  - PT_MV_STRING8
70                  *  - PT_MV_BINARY
71                  *  - PT_MV_CLSID
72                  *  - PT_MV_UNICODE
73                  *  - PT_MV_SYSTIME
74                  *  - PT_NULL
75                  *  - PT_OBJECT
76                  */
77                 int get_type()
78                 {
79                         if (m_property_values) {
80                                 return m_property_values->ulPropTag & 0xffff;
81                         } else if (m_mapi_property_values) {
82                                 return m_mapi_property_values->ulPropTag & 0xffff;
83                         } else {
84                                 return MAPI_PROP_RESERVED;
85                         }
86                 }
87
88                 /**
89                  * \brief Get Property Tag of the Property Value this operator points to.
90                  *
91                  * \return Property Tag of Property this iterator points to or MAPI_PROP_RESERVED if this is an invalid iterator.
92                  */
93                 int get_tag()
94                 {
95                         if (m_property_values) {
96                                 return m_property_values->ulPropTag;
97                         } else if (m_mapi_property_values) {
98                                 return m_mapi_property_values->ulPropTag;
99                         } else {
100                                 return MAPI_PROP_RESERVED;
101                         }
102                 }
103
104                 /// operator++
105                 property_container_iterator& operator++() // prefix
106                 {
107                         if (m_property_values)
108                                 ++m_property_values;
109                         else if (m_mapi_property_values)
110                                 ++m_mapi_property_values;
111
112                         return *this;
113                 }
114
115                 /// operator++ postfix
116                 property_container_iterator operator++(int postfix) // postfix
117                 {
118                         property_container_iterator retval = *this;
119                         if (m_property_values)
120                                  ++m_property_values;
121                         else if (m_mapi_property_values)
122                                 ++m_mapi_property_values;
123
124                         return retval;
125                 }
126                 
127                 /// operator==
128                 bool operator==(const property_container_iterator& rhs) const
129                 {
130                         return ( (m_property_values == rhs.m_property_values) && (m_mapi_property_values == rhs.m_mapi_property_values) );
131                 }
132
133                 /// operator!=
134                 bool operator!=(const property_container_iterator& rhs) const
135                 {
136                         return !(*this == rhs);
137                 }
138
139                 /**
140                  * \brief operator*
141                  *
142                  * \return The property value as a void pointer.
143                  */
144                 const void* operator*()
145                 {
146                         if (m_property_values)
147                                 return get_SPropValue_data(m_property_values);
148                         else
149                                 return get_mapi_SPropValue_data(m_mapi_property_values);
150                 }               
151
152         private:
153                 SPropValue*             m_property_values;
154                 mapi_SPropValue*        m_mapi_property_values;
155 };
156
157
158 /// A container of properties to be used with classes derived from object.
159 class property_container {
160
161         public:
162                 typedef property_container_iterator     iterator;
163                 typedef const void*                     value_type;
164
165                 /// Constructor
166                 property_container(TALLOC_CTX* memory_ctx, mapi_object_t& mapi_object) : 
167                 m_memory_ctx(memory_ctx), m_mapi_object(mapi_object), m_fetched(false), m_property_tag_array(NULL), m_cn_vals(0), m_property_values(0)
168                 {
169                         m_property_value_array.cValues = 0;
170                         m_property_value_array.lpProps = NULL;
171                 }
172
173                 /**
174                  * \brief Fetches properties with the tags supplied using operator<<
175                  *
176                  * \return The number of objects that were fetched.
177                  */
178                 uint32_t fetch()
179                 {
180                         if (GetProps(&m_mapi_object, m_property_tag_array, &m_property_values, &m_cn_vals) != MAPI_E_SUCCESS)
181                                 throw mapi_exception(GetLastError(), "property_container::fetch : GetProps");
182
183                         MAPIFreeBuffer(m_property_tag_array);
184                         m_property_tag_array = NULL;
185
186                         m_fetched = true;
187                         return m_cn_vals;
188                 }
189
190                 /// \brief Fetches \b ALL properties of the object associated with this container.
191                 void fetch_all()
192                 {
193                         if (GetPropsAll(&m_mapi_object, &m_property_value_array) != MAPI_E_SUCCESS)
194                                 throw mapi_exception(GetLastError(), "property_container::fetch_all : GetPropsAll");
195
196                         // Free property_tag_array in case user used operator<< by mistake.
197                         if (m_property_tag_array) {
198                                 MAPIFreeBuffer(m_property_tag_array);
199                                 m_property_tag_array = NULL;
200                         }
201
202                         m_fetched = true;
203                 }
204
205                 /// \brief Adds a Property Tag to be fetched by fetch().
206                 property_container& operator<<(uint32_t property_tag)
207                 {
208                         if (!m_property_tag_array) {
209                                 m_property_tag_array = set_SPropTagArray(m_memory_ctx, 1, property_tag);
210                         } else {
211                                 if (SPropTagArray_add(m_memory_ctx, m_property_tag_array, (enum MAPITAGS)property_tag) != MAPI_E_SUCCESS)
212                                         throw mapi_exception(GetLastError(), "property_container::operator<< : SPropTagArray_add");
213                         }
214
215                         return *this;
216                 }
217
218                 /**
219                  * \brief Finds the property value associated with a property tag
220                  *
221                  * \param property_tag The Property Tag to be searched for
222                  *
223                  * \return Property Value as a const void pointer
224                  */
225                 const void* operator[](uint32_t property_tag)
226                 {
227                         if (!m_fetched) return NULL;
228
229                         if (m_property_values)
230                                 return find_SPropValue_value(property_tag);
231                         else
232                                 return find_mapi_SPropValue_data(&m_property_value_array, property_tag);
233                 }
234
235                 enum MAPITAGS get_tag_at(uint32_t pos)
236                 {
237                         if (m_property_values)
238                                 return m_property_values[pos].ulPropTag;
239                         else
240                                 return m_property_value_array.lpProps[pos].ulPropTag;
241                 }
242
243                 iterator begin() const
244                 {
245                         if (!m_fetched) return iterator();
246                 
247                         if (m_property_values)
248                                 return iterator(m_property_values);
249                         else
250                                 return iterator(m_property_value_array.lpProps);
251                 }
252
253                 iterator end() const
254                 {
255                         if (!m_fetched) return iterator();
256                         
257                         if (m_property_values)
258                                 return iterator(m_property_values + m_cn_vals);
259                         else
260                                 return iterator(m_property_value_array.lpProps + m_property_value_array.cValues);
261                 }
262
263                 /// \brief Get number of properties in container.
264                 size_t size() const
265                 {
266                         if (!m_fetched) return 0;
267
268                         if (m_property_values)
269                                 return m_cn_vals;
270                         else
271                                 return m_property_value_array.cValues;
272                 }
273
274                 /// Destructor
275                 ~property_container()
276                 {
277                         if (m_property_tag_array) MAPIFreeBuffer(m_property_tag_array);
278                 }
279
280         private:
281                 TALLOC_CTX*             m_memory_ctx;
282                 mapi_object_t&          m_mapi_object;
283
284                 bool                    m_fetched;
285
286                 SPropTagArray*          m_property_tag_array;
287
288                 // Used when calling GetProps (fetch)
289                 uint32_t                m_cn_vals;
290                 SPropValue*             m_property_values;
291
292                 // Used when calling GetPropsAll (fetch_all)
293                 mapi_SPropValue_array   m_property_value_array;
294
295                 const void* find_SPropValue_value(uint32_t property_tag)
296                 {
297                         for (uint32_t i = 0; i < m_cn_vals; ++i)
298                         {
299                           if ((uint32_t)m_property_values[i].ulPropTag == property_tag)
300                                         return get_SPropValue_data(&m_property_values[i]);
301                         }
302
303                         return NULL;
304                 }
305 };
306
307 } // namespace libmapipp
308
309 #endif //!LIBMAPIPP__PROPERTY_CONTAINER_H__