diff options
Diffstat (limited to 'src/property_list_service.c')
| -rw-r--r-- | src/property_list_service.c | 116 |
1 files changed, 60 insertions, 56 deletions
diff --git a/src/property_list_service.c b/src/property_list_service.c index f411699..a6e3e24 100644 --- a/src/property_list_service.c +++ b/src/property_list_service.c | |||
| @@ -48,6 +48,10 @@ static property_list_service_error_t service_to_property_list_service_error(serv | |||
| 48 | return PROPERTY_LIST_SERVICE_E_MUX_ERROR; | 48 | return PROPERTY_LIST_SERVICE_E_MUX_ERROR; |
| 49 | case SERVICE_E_SSL_ERROR: | 49 | case SERVICE_E_SSL_ERROR: |
| 50 | return PROPERTY_LIST_SERVICE_E_SSL_ERROR; | 50 | return PROPERTY_LIST_SERVICE_E_SSL_ERROR; |
| 51 | case SERIVCE_E_NOT_ENOUGH_DATA: | ||
| 52 | return PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA; | ||
| 53 | case SERVICE_E_TIMEOUT: | ||
| 54 | return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; | ||
| 51 | default: | 55 | default: |
| 52 | break; | 56 | break; |
| 53 | } | 57 | } |
| @@ -108,7 +112,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c | |||
| 108 | char *content = NULL; | 112 | char *content = NULL; |
| 109 | uint32_t length = 0; | 113 | uint32_t length = 0; |
| 110 | uint32_t nlen = 0; | 114 | uint32_t nlen = 0; |
| 111 | int bytes = 0; | 115 | uint32_t bytes = 0; |
| 112 | 116 | ||
| 113 | if (!client || (client && !client->parent) || !plist) { | 117 | if (!client || (client && !client->parent) || !plist) { |
| 114 | return PROPERTY_LIST_SERVICE_E_INVALID_ARG; | 118 | return PROPERTY_LIST_SERVICE_E_INVALID_ARG; |
| @@ -126,13 +130,13 @@ static property_list_service_error_t internal_plist_send(property_list_service_c | |||
| 126 | 130 | ||
| 127 | nlen = htobe32(length); | 131 | nlen = htobe32(length); |
| 128 | debug_info("sending %d bytes", length); | 132 | debug_info("sending %d bytes", length); |
| 129 | service_send(client->parent, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | 133 | service_send(client->parent, (const char*)&nlen, sizeof(nlen), &bytes); |
| 130 | if (bytes == sizeof(nlen)) { | 134 | if (bytes == sizeof(nlen)) { |
| 131 | service_send(client->parent, content, length, (uint32_t*)&bytes); | 135 | service_send(client->parent, content, length, &bytes); |
| 132 | if (bytes > 0) { | 136 | if (bytes > 0) { |
| 133 | debug_info("sent %d bytes", bytes); | 137 | debug_info("sent %d bytes", bytes); |
| 134 | debug_plist(plist); | 138 | debug_plist(plist); |
| 135 | if ((uint32_t)bytes == length) { | 139 | if (bytes == length) { |
| 136 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; | 140 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; |
| 137 | } else { | 141 | } else { |
| 138 | debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length); | 142 | debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length); |
| @@ -145,7 +149,6 @@ static property_list_service_error_t internal_plist_send(property_list_service_c | |||
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | free(content); | 151 | free(content); |
| 148 | |||
| 149 | return res; | 152 | return res; |
| 150 | } | 153 | } |
| 151 | 154 | ||
| @@ -170,6 +173,8 @@ LIBIMOBILEDEVICE_API property_list_service_error_t property_list_service_send_bi | |||
| 170 | * | 173 | * |
| 171 | * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, | 174 | * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, |
| 172 | * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, | 175 | * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, |
| 176 | * PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA when not enough data | ||
| 177 | * received, PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT when the connection times out, | ||
| 173 | * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be | 178 | * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be |
| 174 | * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a | 179 | * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a |
| 175 | * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR | 180 | * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR |
| @@ -187,65 +192,64 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis | |||
| 187 | 192 | ||
| 188 | *plist = NULL; | 193 | *plist = NULL; |
| 189 | service_error_t serr = service_receive_with_timeout(client->parent, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); | 194 | service_error_t serr = service_receive_with_timeout(client->parent, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); |
| 190 | if ((serr == SERVICE_E_SUCCESS) && (bytes == 0)) { | 195 | if (serr != SERVICE_E_SUCCESS) { |
| 191 | return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; | 196 | debug_info("initial read failed!"); |
| 197 | return service_to_property_list_service_error(serr); | ||
| 192 | } | 198 | } |
| 199 | |||
| 193 | debug_info("initial read=%i", bytes); | 200 | debug_info("initial read=%i", bytes); |
| 194 | if (bytes < 4) { | ||
| 195 | debug_info("initial read failed!"); | ||
| 196 | return PROPERTY_LIST_SERVICE_E_MUX_ERROR; | ||
| 197 | } else { | ||
| 198 | uint32_t curlen = 0; | ||
| 199 | char *content = NULL; | ||
| 200 | 201 | ||
| 201 | pktlen = be32toh(pktlen); | 202 | uint32_t curlen = 0; |
| 202 | debug_info("%d bytes following", pktlen); | 203 | char *content = NULL; |
| 203 | content = (char*)malloc(pktlen); | ||
| 204 | if (!content) { | ||
| 205 | debug_info("out of memory when allocating %d bytes", pktlen); | ||
| 206 | return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; | ||
| 207 | } | ||
| 208 | 204 | ||
| 209 | while (curlen < pktlen) { | 205 | pktlen = be32toh(pktlen); |
| 210 | service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); | 206 | debug_info("%d bytes following", pktlen); |
| 211 | if (bytes <= 0) { | 207 | content = (char*)malloc(pktlen); |
| 212 | res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; | 208 | if (!content) { |
| 213 | break; | 209 | debug_info("out of memory when allocating %d bytes", pktlen); |
| 214 | } | 210 | return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; |
| 215 | debug_info("received %d bytes", bytes); | 211 | } |
| 216 | curlen += bytes; | 212 | |
| 217 | } | 213 | while (curlen < pktlen) { |
| 218 | if (curlen < pktlen) { | 214 | serr = service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); |
| 219 | debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); | 215 | if (serr != SERVICE_E_SUCCESS) { |
| 220 | if (curlen > 0) { | 216 | res = service_to_property_list_service_error(serr); |
| 221 | debug_info("incomplete packet following:"); | 217 | break; |
| 222 | debug_buffer(content, curlen); | ||
| 223 | } | ||
| 224 | free(content); | ||
| 225 | return res; | ||
| 226 | } | ||
| 227 | if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { | ||
| 228 | plist_from_bin(content, pktlen, plist); | ||
| 229 | } else if ((pktlen > 5) && !memcmp(content, "<?xml", 5)) { | ||
| 230 | /* iOS 4.3+ hack: plist data might contain invalid characters, thus we convert those to spaces */ | ||
| 231 | for (bytes = 0; bytes < pktlen-1; bytes++) { | ||
| 232 | if ((content[bytes] >= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) | ||
| 233 | content[bytes] = 0x20; | ||
| 234 | } | ||
| 235 | plist_from_xml(content, pktlen, plist); | ||
| 236 | } else { | ||
| 237 | debug_info("WARNING: received unexpected non-plist content"); | ||
| 238 | debug_buffer(content, pktlen); | ||
| 239 | } | 218 | } |
| 240 | if (*plist) { | 219 | debug_info("received %d bytes", bytes); |
| 241 | debug_plist(*plist); | 220 | curlen += bytes; |
| 242 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; | 221 | } |
| 243 | } else { | 222 | if (curlen < pktlen) { |
| 244 | res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; | 223 | debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); |
| 224 | if (curlen > 0) { | ||
| 225 | debug_info("incomplete packet following:"); | ||
| 226 | debug_buffer(content, curlen); | ||
| 245 | } | 227 | } |
| 246 | free(content); | 228 | free(content); |
| 247 | content = NULL; | 229 | return res; |
| 248 | } | 230 | } |
| 231 | if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { | ||
| 232 | plist_from_bin(content, pktlen, plist); | ||
| 233 | } else if ((pktlen > 5) && !memcmp(content, "<?xml", 5)) { | ||
| 234 | /* iOS 4.3+ hack: plist data might contain invalid characters, thus we convert those to spaces */ | ||
| 235 | for (bytes = 0; bytes < pktlen-1; bytes++) { | ||
| 236 | if ((content[bytes] >= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) | ||
| 237 | content[bytes] = 0x20; | ||
| 238 | } | ||
| 239 | plist_from_xml(content, pktlen, plist); | ||
| 240 | } else { | ||
| 241 | debug_info("WARNING: received unexpected non-plist content"); | ||
| 242 | debug_buffer(content, pktlen); | ||
| 243 | } | ||
| 244 | if (*plist) { | ||
| 245 | debug_plist(*plist); | ||
| 246 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; | ||
| 247 | } else { | ||
| 248 | res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; | ||
| 249 | } | ||
| 250 | free(content); | ||
| 251 | content = NULL; | ||
| 252 | |||
| 249 | return res; | 253 | return res; |
| 250 | } | 254 | } |
| 251 | 255 | ||
