File: | activesyncd/eas-daemon/libeas/eas-ping-msg.c |
Warning: | line 216, column 6 Access to field 'type' results in a dereference of a null pointer (loaded from variable 'node') |
1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8; show-trailing-whitespace: t -*- */ | |||
2 | /* | |||
3 | * ActiveSync core protocol library | |||
4 | * | |||
5 | * Copyright © 2011 Intel Corporation. | |||
6 | * | |||
7 | * Authors: Mobica Ltd. <www.mobica.com> | |||
8 | * | |||
9 | * This file is provided under a dual Apache/LGPLv2.1 licence. When | |||
10 | * using or redistributing this file, you may do so under either | |||
11 | * licence. | |||
12 | * | |||
13 | * | |||
14 | * LGPLv2.1 LICENCE SUMMARY | |||
15 | * | |||
16 | * Copyright © Intel Corporation, dates as above. | |||
17 | * | |||
18 | * This library is free software; you can redistribute it and/or | |||
19 | * modify it under the terms of the GNU Lesser General Public | |||
20 | * License as published by the Free Software Foundation; either | |||
21 | * version 2.1 of the License, or (at your option) any later | |||
22 | * version. | |||
23 | * | |||
24 | * This library is distributed in the hope that it will be useful, | |||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
27 | * Lesser General Public License for more details. | |||
28 | * | |||
29 | * You should have received a copy of the GNU Lesser General Public | |||
30 | * License along with this library; if not, write to the Free | |||
31 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |||
32 | * Boston, MA 02110-1301 USA | |||
33 | * | |||
34 | * | |||
35 | * APACHE LICENCE SUMMARY | |||
36 | * | |||
37 | * Copyright © Intel Corporation, dates as above. | |||
38 | * | |||
39 | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
40 | * you may not use this file except in compliance with the License. | |||
41 | * You may obtain a copy of the License at | |||
42 | * | |||
43 | * http://www.apache.org/licenses/LICENSE-2.0 | |||
44 | * | |||
45 | * Unless required by applicable law or agreed to in writing, software | |||
46 | * distributed under the License is distributed on an "AS IS" BASIS, | |||
47 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
48 | * See the License for the specific language governing permissions and | |||
49 | * limitations under the License. | |||
50 | * | |||
51 | */ | |||
52 | ||||
53 | #include "eas-connection-errors.h" | |||
54 | #include "eas-ping-msg.h" | |||
55 | #include "eas-email-info-translator.h" | |||
56 | #include "eas-connection-errors.h" | |||
57 | #include <eas-folder.h> | |||
58 | ||||
59 | struct _EasPingMsgPrivate { | |||
60 | GSList* updated_folders; | |||
61 | EasPingReqState state; | |||
62 | }; | |||
63 | ||||
64 | #define EAS_PING_MSG_PRIVATE(o)(((EasPingMsgPrivate*) g_type_instance_get_private ((GTypeInstance *) ((o)), ((eas_ping_msg_get_type ()))))) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EAS_TYPE_PING_MSG, EasPingMsgPrivate)((EasPingMsgPrivate*) g_type_instance_get_private ((GTypeInstance *) ((o)), ((eas_ping_msg_get_type ()))))) | |||
65 | ||||
66 | ||||
67 | G_DEFINE_TYPE (EasPingMsg, eas_ping_msg, EAS_TYPE_MSG_BASE)static void eas_ping_msg_init (EasPingMsg *self); static void eas_ping_msg_class_init (EasPingMsgClass *klass); static gpointer eas_ping_msg_parent_class = ((void*)0); static gint EasPingMsg_private_offset ; static void eas_ping_msg_class_intern_init (gpointer klass) { eas_ping_msg_parent_class = g_type_class_peek_parent (klass ); if (EasPingMsg_private_offset != 0) g_type_class_adjust_private_offset (klass, &EasPingMsg_private_offset); eas_ping_msg_class_init ((EasPingMsgClass*) klass); } __attribute__((__unused__)) static inline gpointer eas_ping_msg_get_instance_private (EasPingMsg *self) { return (((gpointer) ((guint8*) (self) + (glong) (EasPingMsg_private_offset )))); } GType eas_ping_msg_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if ((__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_7[(sizeof *(&g_define_type_id__volatile ) == sizeof (gpointer)) ? 1 : -1] __attribute__((__unused__)) ; (void) (0 ? (gpointer) *(&g_define_type_id__volatile) : 0); (!(__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_8 [(sizeof *(&g_define_type_id__volatile) == sizeof (gpointer )) ? 1 : -1] __attribute__((__unused__)); __sync_synchronize ( ); (gpointer) *(&g_define_type_id__volatile); })) && g_once_init_enter (&g_define_type_id__volatile)); }))) { GType g_define_type_id = g_type_register_static_simple ((eas_msg_base_get_type ()), g_intern_static_string ("EasPingMsg"), sizeof (EasPingMsgClass ), (GClassInitFunc) eas_ping_msg_class_intern_init, sizeof (EasPingMsg ), (GInstanceInitFunc) eas_ping_msg_init, (GTypeFlags) 0); { { {};} } (__extension__ ({ typedef char _GStaticAssertCompileTimeAssertion_9 [(sizeof *(&g_define_type_id__volatile) == sizeof (gpointer )) ? 1 : -1] __attribute__((__unused__)); (void) (0 ? *(& g_define_type_id__volatile) = (g_define_type_id) : 0); g_once_init_leave ((&g_define_type_id__volatile), (gsize) (g_define_type_id )); })); } return g_define_type_id__volatile; }; | |||
68 | ||||
69 | static void | |||
70 | eas_ping_msg_init (EasPingMsg *object) | |||
71 | { | |||
72 | EasPingMsgPrivate *priv; | |||
73 | g_debug ("eas_ping_msg_init++"); | |||
74 | ||||
75 | object->priv = priv = EAS_PING_MSG_PRIVATE (object)(((EasPingMsgPrivate*) g_type_instance_get_private ((GTypeInstance *) ((object)), ((eas_ping_msg_get_type ()))))); | |||
76 | ||||
77 | g_debug ("eas_ping_msg_init--"); | |||
78 | } | |||
79 | ||||
80 | static void | |||
81 | eas_ping_msg_finalize (GObject *object) | |||
82 | { | |||
83 | G_OBJECT_CLASS (eas_ping_msg_parent_class)((((GObjectClass*) g_type_check_class_cast ((GTypeClass*) ((eas_ping_msg_parent_class )), (((GType) ((20) << (2))))))))->finalize (object); | |||
84 | } | |||
85 | ||||
86 | static void | |||
87 | eas_ping_msg_class_init (EasPingMsgClass *klass) | |||
88 | { | |||
89 | GObjectClass* object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) g_type_check_class_cast ((GTypeClass*) ((klass )), (((GType) ((20) << (2)))))))); | |||
90 | ||||
91 | g_type_class_add_private (klass, sizeof (EasPingMsgPrivate)); | |||
92 | ||||
93 | object_class->finalize = eas_ping_msg_finalize; | |||
94 | } | |||
95 | ||||
96 | EasPingMsg* | |||
97 | eas_ping_msg_new () | |||
98 | { | |||
99 | EasPingMsg* msg = NULL((void*)0); | |||
100 | msg = g_object_new (EAS_TYPE_PING_MSG(eas_ping_msg_get_type ()), NULL((void*)0)); | |||
101 | return msg; | |||
102 | } | |||
103 | ||||
104 | xmlDoc* | |||
105 | eas_ping_msg_build_message (EasPingMsg* self, const gchar* accountId, const gchar *heartbeat, GSList *folders) | |||
106 | { | |||
107 | xmlDoc *doc = NULL((void*)0); | |||
108 | xmlNode *node = NULL((void*)0), | |||
109 | *child = NULL((void*)0), | |||
110 | *folder = NULL((void*)0); | |||
111 | GSList * iterator; | |||
112 | gchar *folder_id = NULL((void*)0); | |||
113 | ||||
114 | doc = xmlNewDoc ( (xmlChar *) "1.0"); | |||
115 | node = xmlNewDocNode (doc, NULL((void*)0), (xmlChar*) "Ping", NULL((void*)0)); | |||
116 | xmlDocSetRootElement (doc, node); | |||
117 | ||||
118 | xmlCreateIntSubset (doc, | |||
119 | (xmlChar*) "ActiveSync", | |||
120 | (xmlChar*) "-//MICROSOFT//DTD ActiveSync//EN", | |||
121 | (xmlChar*) "http://www.microsoft.com/"); | |||
122 | ||||
123 | xmlNewNs (node, (xmlChar *) "Ping:", NULL((void*)0)); | |||
124 | child = xmlNewChild (node, NULL((void*)0), (xmlChar *) "HeartbeatInterval", (xmlChar*) heartbeat); | |||
125 | child = xmlNewChild (node, NULL((void*)0), (xmlChar *) "Folders", NULL((void*)0)); | |||
126 | for (iterator = folders; iterator; iterator = iterator->next) { | |||
127 | folder_id = (gchar*) iterator->data; | |||
128 | folder = xmlNewChild (child, NULL((void*)0), (xmlChar *) "Folder", NULL((void*)0)); | |||
129 | xmlNewChild (folder, NULL((void*)0), (xmlChar *) "Id", (xmlChar*) (folder_id)); | |||
130 | //TODO:class needs to be set properly... need some sort of lookup from type probably | |||
131 | xmlNewChild (folder, NULL((void*)0), (xmlChar *) "Class", (xmlChar*) "Email"); | |||
132 | } | |||
133 | ||||
134 | return doc; | |||
135 | } | |||
136 | ||||
137 | ||||
138 | gboolean | |||
139 | eas_ping_msg_parse_response (EasPingMsg* self, xmlDoc *doc, GError** error) | |||
140 | { | |||
141 | gboolean ret = TRUE(!(0)); | |||
142 | EasPingMsgPrivate *priv = self->priv; | |||
143 | xmlNode *node = NULL((void*)0), | |||
144 | *appData = NULL((void*)0); | |||
145 | EasError error_details; | |||
146 | gchar* folderid = NULL((void*)0); | |||
147 | ||||
148 | ||||
149 | g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do{ if (__builtin_expect (__extension__ ({ int _g_boolean_var_ ; if ((error == ((void*)0) || *error == ((void*)0))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 1)) { } else { g_return_if_fail_warning ("libeas", ((const char*) (__func__ )), "error == NULL || *error == NULL"); return ((0)); }; }while (0); | |||
150 | ||||
151 | if (!doc) { | |||
| ||||
152 | g_set_error (error, EAS_CONNECTION_ERROR(eas_connection_error_quark ()), | |||
153 | EAS_CONNECTION_ERROR_XMLELEMENTNOTFOUND, | |||
154 | ("Ping Response is empty")); | |||
155 | ret = FALSE(0); | |||
156 | goto finish; | |||
157 | } | |||
158 | node = xmlDocGetRootElement ( (xmlDoc*) doc); | |||
159 | if (g_strcmp0 ( (char *) node->name, "Ping")) { | |||
160 | g_set_error (error, EAS_CONNECTION_ERROR(eas_connection_error_quark ()), | |||
161 | EAS_CONNECTION_ERROR_XMLELEMENTNOTFOUND, | |||
162 | ("Failed to find <Ping> element")); | |||
163 | ret = FALSE(0); | |||
164 | goto finish; | |||
165 | } | |||
166 | for (node = node->children; node; node = node->next) { | |||
167 | if (node->type == XML_ELEMENT_NODE && !g_strcmp0 ( (char *) node->name, "Status")) { | |||
168 | gchar *sync_status = (gchar *) xmlNodeGetContent (node); | |||
169 | guint status_num = atoi (sync_status); | |||
170 | xmlFree (sync_status); | |||
171 | switch (status_num) { | |||
172 | // Ping completed with no changes - re-issue command ( headers only) | |||
173 | case EAS_COMMON_STATUS_OK: { | |||
174 | g_debug ("Status 1 - resend heartbeat "); | |||
175 | priv->state = EasPingReqSendHeartbeat; | |||
176 | goto finish; | |||
177 | } | |||
178 | break; | |||
179 | // Ping completed with some folder changes - notify client to sync folders | |||
180 | case EAS_PING_STATUS_FOLDERS_UPDATED: { | |||
181 | g_debug ("Status 2 - notify client "); | |||
182 | priv->state = EasPingReqNotifyClient; | |||
183 | } | |||
184 | break; | |||
185 | default: { | |||
186 | ret = FALSE(0); | |||
187 | g_debug ("error status - return error"); | |||
188 | if ( (EAS_PING_STATUS_FOLDERS_UPDATED < status_num) && (status_num <= EAS_PING_STATUS_FOLDER_HIERARCHY_ERROR)) { // it's a ping status code | |||
189 | error_details = ping_status_error_map[status_num]; | |||
190 | } else { | |||
191 | if (status_num > EAS_PING_STATUS_EXCEEDSSTATUSLIMIT) // not pretty, but make sure we don't overrun array if new status added | |||
192 | status_num = EAS_PING_STATUS_EXCEEDSSTATUSLIMIT; | |||
193 | ||||
194 | error_details = ping_status_error_map[status_num]; | |||
195 | } | |||
196 | g_set_error (error, EAS_CONNECTION_ERROR(eas_connection_error_quark ()), error_details.code, "%s", error_details.message); | |||
197 | goto finish; | |||
198 | } | |||
199 | } | |||
200 | continue; | |||
201 | } | |||
202 | if (node->type == XML_ELEMENT_NODE && !g_strcmp0 ( (char *) node->name, "Folders")) { | |||
203 | g_debug ("Got Folders "); | |||
204 | break; | |||
205 | } | |||
206 | if (node->type == XML_ELEMENT_NODE && !g_strcmp0 ( (char *) node->name, "HeartbeatInterval")) { | |||
207 | g_debug ("Got <HeartbeatInterval/>"); | |||
208 | break; | |||
209 | } | |||
210 | if (node->type == XML_ELEMENT_NODE && !g_strcmp0 ( (char *) node->name, "MaxFolders")) { | |||
211 | g_debug ("Got <MaxFolders/>"); | |||
212 | break; | |||
213 | } | |||
214 | } | |||
215 | g_debug ("about to parse folders"); | |||
216 | if (node->type == XML_ELEMENT_NODE && !g_strcmp0 ( (char *) node->name, "Folders")) { | |||
| ||||
217 | g_debug ("parsing folders"); | |||
218 | appData = node; | |||
219 | for (appData = appData->children; appData; appData = appData->next) { | |||
220 | if (appData->type == XML_ELEMENT_NODE && !g_strcmp0 ( (char *) appData->name, "Folder")) { | |||
221 | //TODO: fix memory cleanup for this... | |||
222 | folderid = (gchar *) xmlNodeGetContent (appData); | |||
223 | priv->updated_folders = g_slist_append (priv->updated_folders, folderid); | |||
224 | } | |||
225 | } | |||
226 | } | |||
227 | g_debug ("eas_ping_msg_parse_response--"); | |||
228 | ||||
229 | finish: | |||
230 | if (!ret) { | |||
231 | g_assert (error == NULL || *error != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_ ; if ((error == ((void*)0) || *error != ((void*)0))) _g_boolean_var_ = 1; else _g_boolean_var_ = 0; _g_boolean_var_; }), 1)) ; else g_assertion_message_expr ("libeas", "/data/runtests/work/sources/activesyncd/eas-daemon/libeas/eas-ping-msg.c" , 231, ((const char*) (__func__)), "error == NULL || *error != NULL" ); } while (0); | |||
232 | } | |||
233 | return ret; | |||
234 | } | |||
235 | ||||
236 | EasPingReqState | |||
237 | eas_ping_msg_get_state (EasPingMsg *self) | |||
238 | { | |||
239 | EasPingMsgPrivate *priv = self->priv; | |||
240 | g_debug ("eas_ping_msg_get_state +-"); | |||
241 | return priv->state; | |||
242 | ||||
243 | } | |||
244 | ||||
245 | GSList* | |||
246 | eas_ping_msg_get_changed_folders (EasPingMsg* self) | |||
247 | { | |||
248 | EasPingMsgPrivate *priv = self->priv; | |||
249 | return priv->updated_folders; | |||
250 | } | |||
251 | ||||
252 | ||||
253 |