ArvZip * arv_zip_new (const void *buffer, size_t size) { ArvZip *zip; const void *ptr; int i; gboolean directory_found; g_return_val_if_fail (buffer != NULL, NULL); g_return_val_if_fail (size > 0, NULL); zip = g_new0 (ArvZip, 1); zip->buffer = buffer; zip->buffer_size = size; directory_found = FALSE; for (i = zip->buffer_size - 4; i > 0; i--) { if (zip->buffer[i] == 0x50 && zip->buffer[i+1] == 0x4b && zip->buffer[i+2] == 0x05 && zip->buffer[i+3] == 0x06) { zip->directory_position = i; directory_found = TRUE; break; } } if (!directory_found) { arv_debug_misc ("[Zip::new] Magic number for end of central directory not found (0x06054b50)"); return zip; } ptr = zip->buffer + zip->directory_position; zip->n_files = ARV_GUINT16_FROM_LE_PTR (ptr, 10); if (ARV_GUINT16_FROM_LE_PTR (ptr, 8) != zip->n_files) { arv_debug_misc ("[Zip::new] Mismatch in number of files"); zip->n_files = 0; return zip; } zip->directory_size = ARV_GUINT32_FROM_LE_PTR (ptr, 12); zip->directory_offset = ARV_GUINT32_FROM_LE_PTR (ptr, 16); zip->header_size = zip->directory_position - (zip->directory_offset + zip->directory_size); arv_log_misc ("[Zip::new] number of files = %d", zip->n_files); arv_log_misc ("[Zip::new] directory position = 0x%08x", zip->directory_position); arv_log_misc ("[Zip::new] directory size = %d", zip->directory_size); arv_log_misc ("[Zip::new] directory offset = 0x%08x", zip->directory_offset); arv_log_misc ("[Zip::new] header size = %d", zip->header_size); arv_zip_build_file_list (zip); return zip; }
static void arv_zip_build_file_list (ArvZip *zip) { ArvZipFile *zip_file; const void *ptr; ptrdiff_t offset; guint i; offset = zip->directory_offset; for (i = 0; i < zip->n_files; i++) { ptr = zip->buffer + zip->header_size + offset; if (ARV_GUINT32_FROM_LE_PTR (ptr, 0) != 0x02014b50) { arv_debug_misc ("[Zip::build_file_list] Magic number of central directory not found (0x02014b50)"); arv_debug_misc ("[Zip::build_file_list] Expected at 0x%08x - found 0x%08x instead", zip->header_size + offset, ARV_GUINT32_FROM_LE_PTR (ptr, 0)); return; } zip_file = g_new0 (ArvZipFile, 1); zip_file->compressed_size = ARV_GUINT32_FROM_LE_PTR (ptr, 20); zip_file->uncompressed_size = ARV_GUINT32_FROM_LE_PTR (ptr, 24); zip_file->offset = ARV_GUINT32_FROM_LE_PTR (ptr, 42); zip_file->name = g_strndup (((char *) ptr) + 46, ARV_GUINT16_FROM_LE_PTR (ptr, 28)); arv_log_misc ("[Zip::list_files] %s", zip_file->name); zip->files = g_slist_prepend (zip->files, zip_file); offset += 0x2e + ARV_GUINT16_FROM_LE_PTR (ptr, 28) + /* filename size */ ARV_GUINT16_FROM_LE_PTR (ptr, 30) + /* extra field */ ARV_GUINT16_FROM_LE_PTR (ptr, 32); /* file comment */ } }
static char * _load_genicam (ArvGvDevice *gv_device, guint32 address, size_t *size) { char filename[ARV_GVBS_XML_URL_SIZE]; char **tokens; char *genicam = NULL; g_return_val_if_fail (size != NULL, NULL); *size = 0; if (!arv_device_read_memory (ARV_DEVICE (gv_device), address, ARV_GVBS_XML_URL_SIZE, filename, NULL)) return NULL; filename[ARV_GVBS_XML_URL_SIZE - 1] = '\0'; arv_debug_device ("[GvDevice::load_genicam] xml url = '%s' at 0x%x", filename, address); tokens = g_regex_split (arv_gv_device_get_url_regex (), filename, 0); if (tokens[0] != NULL) { if (g_strcmp0 (tokens[1], "File:") == 0) g_file_get_contents (filename, &genicam, NULL, NULL); else if (g_strcmp0 (tokens[1], "Local:") == 0 && tokens[2] != NULL && tokens[3] != NULL && tokens[4] != NULL) { guint32 file_address; guint32 file_size; file_address = strtoul (tokens[3], NULL, 16); file_size = strtoul (tokens[4], NULL, 16); arv_debug_device ("[GvDevice::load_genicam] Xml address = 0x%x - size = 0x%x - %s", file_address, file_size, tokens[2]); if (file_size > 0) { genicam = g_malloc (file_size); if (arv_device_read_memory (ARV_DEVICE (gv_device), file_address, file_size, genicam, NULL)) { if (arv_debug_check (&arv_debug_category_misc, ARV_DEBUG_LEVEL_LOG)) { GString *string = g_string_new (""); g_string_append_printf (string, "[GvDevice::load_genicam] Raw data size = 0x%x\n", file_size); arv_g_string_append_hex_dump (string, genicam, file_size); arv_log_misc ("%s", string->str); g_string_free (string, TRUE); } if (g_str_has_suffix (tokens[2], ".zip")) { ArvZip *zip; const GSList *zip_files; arv_debug_device ("[GvDevice::load_genicam] Zipped xml data"); zip = arv_zip_new (genicam, file_size); zip_files = arv_zip_get_file_list (zip); if (zip_files != NULL) { const char *zip_filename; void *tmp_buffer; size_t tmp_buffer_size; zip_filename = arv_zip_file_get_name (zip_files->data); tmp_buffer = arv_zip_get_file (zip, zip_filename, &tmp_buffer_size); g_free (genicam); file_size = tmp_buffer_size; genicam = tmp_buffer; } else arv_warning_device ("[GvDevice::load_genicam] Invalid format"); arv_zip_free (zip); } *size = file_size; } else { g_free (genicam); genicam = NULL; *size = 0; } } } } g_strfreev (tokens); return genicam; }