/* ArchiveReader::extractCurrentEntry {{{ * */ ZEND_METHOD(ArchiveReader, extractCurrentEntry) { zval *this = getThis(); archive_file_t *arch; int result, error_num, flags = 0; const char *error_string; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (arch->current_entry == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Current archive entry is not available"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (arch->current_entry->data) { /* again, rather annoying libarchive limitation: you can't extract or * read entry anymore if it had been extracted/read before. * */ zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_FALSE; } result = archive_read_extract(arch->arch, arch->current_entry->entry, flags); if (result && result != ARCHIVE_EOF) { error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to extract entry: error #%d, %s", error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to extract entry: unknown error %d", result); } zend_restore_error_handling(&error_handling TSRMLS_CC); return; } zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; }
/* ArchiveReader::getCurrentEntryData {{{ * */ ZEND_METHOD(ArchiveReader, getCurrentEntryData) { zval *this = getThis(); archive_file_t *arch; int result, error_num; size_t len; off_t offset; const char *error_string; char *buf; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (arch->current_entry == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Current archive entry is not available"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (arch->current_entry->data) { zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_STRINGL(arch->current_entry->data, arch->current_entry->data_len, 1); } while ((result = archive_read_data_block(arch->arch, (const void **)&buf, &len, &offset)) == ARCHIVE_OK) { arch->current_entry->data = erealloc(arch->current_entry->data, arch->current_entry->data_len + len + 1); memcpy(arch->current_entry->data + arch->current_entry->data_len, buf, len); arch->current_entry->data_len += len; } if (result && result != ARCHIVE_EOF) { error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read entry data: error #%d, %s", error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read entry data: unknown error %d", result); } zend_restore_error_handling(&error_handling TSRMLS_CC); return; } zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_STRINGL(arch->current_entry->data, arch->current_entry->data_len, 1); }
/* ArchiveReader::readCurrentEntryData(count) {{{ * */ ZEND_METHOD(ArchiveReader, readCurrentEntryData){ zval *this = getThis(); archive_file_t *arch; char *buf; const char *error_string; size_t len; int r, error_num; long count; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &count) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (arch->current_entry == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Current archive entry is not available"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } Z_STRVAL_P(return_value) = emalloc(count+1); len = 0; while(count > 0){ r = archive_read_data(arch->arch, Z_STRVAL_P(return_value)+len, count); if(r < ARCHIVE_OK){ error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompress entry failed errno(%d):%s", error_num, error_string); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if(r == 0){ break; } count -= r; len += r; } Z_STRVAL_P(return_value)[len] = 0; Z_STRLEN_P(return_value) = len; Z_TYPE_P(return_value) = IS_STRING; zend_restore_error_handling(&error_handling TSRMLS_CC); }
/* ArchiveReader::getStream{{{ * * */ ZEND_METHOD(ArchiveReader, getStream){ zval *this = getThis(); archive_file_t *arch; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if(arch->stream){ php_stream_to_zval(arch->stream, return_value); }else{ RETURN_FALSE; } }
/* ArchiveReader::getArchiveFormat{{{ * * */ ZEND_METHOD(ArchiveReader, getArchiveFormat){ long format; zval *this = getThis(); archive_file_t *arch; struct archive *a; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_FALSE; } zend_restore_error_handling(&error_handling TSRMLS_CC); format = archive_format(arch->arch); RETURN_LONG(format); }/*}}}*/
/* ArchiveReader::skipCurrentEntryData{{{ * */ ZEND_METHOD(ArchiveReader, skipCurrentEntryData){ zval *this = getThis(); archive_file_t *arch; zend_error_handling error_handling; int r; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } r = archive_read_data_skip(arch->arch); if(r != ARCHIVE_OK){ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Skip archive entry failed"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } return; }/*}}}*/
/* ArchiveWriter::finish {{{ * */ ZEND_METHOD(ArchiveWriter, finish) { zval *this = getThis(); int resource_id; HashPosition pos; archive_file_t *arch; archive_entry_t **entry; int result, error_num; const char *error_string; mode_t mode; php_stream *stream; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (zend_hash_sort(arch->entries, zend_qsort, _archive_pathname_compare, 0 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } zend_hash_internal_pointer_reset_ex(arch->entries, &pos); while (zend_hash_get_current_data_ex(arch->entries, (void **)&entry, &pos) == SUCCESS) { mode = archive_entry_mode((*entry)->entry); if (S_ISREG(mode) && archive_entry_size((*entry)->entry) > 0) { if ((stream = php_stream_open_wrapper_ex((*entry)->filename, "r", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL))) { char buf[PHP_ARCHIVE_BUF_LEN]; int header_written=0; int read_bytes; while ((read_bytes = php_stream_read(stream, buf, PHP_ARCHIVE_BUF_LEN))) { if (!header_written) { /* write header only after the first successful read */ result = archive_write_header(arch->arch, (*entry)->entry); if (result == ARCHIVE_FATAL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write entry header for file %s: fatal error", (*entry)->filename); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } header_written = 1; } result = archive_write_data(arch->arch, buf, read_bytes); if (result <= 0) { error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write file %s to archive: error #%d, %s", (*entry)->filename, error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write file %s: unknown error %d", (*entry)->filename, result); } php_stream_close(stream); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } } php_stream_close(stream); } } else { result = archive_write_header(arch->arch, (*entry)->entry); if (result == ARCHIVE_FATAL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write entry header for file %s: fatal error", (*entry)->filename); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } } zend_hash_move_forward_ex(arch->entries, &pos); } if ((resource_id = _archive_get_rsrc_id(this TSRMLS_CC))) { add_property_resource(this, "fd", 0); zend_list_delete(resource_id); zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; } php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to finish writing of archive file"); zend_restore_error_handling(&error_handling TSRMLS_CC); }
/* ArchiveWriter::addEntry {{{ * */ ZEND_METHOD(ArchiveWriter, addEntry) { zval *this = getThis(); zval *entry_obj; archive_file_t *arch; archive_entry_t *entry, *entry_copy; char *pathname; int pathname_len; const struct stat *stat_sb; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &entry_obj) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!instanceof_function(Z_OBJCE_P(entry_obj), ce_ArchiveEntry TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An instance of ArchiveEntry is required"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_entry_struct(entry_obj, &entry TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } pathname = entry->filename; pathname_len = strlen(pathname); _archive_normalize_path(&pathname, &pathname_len); if (pathname_len == 0 || pathname[0] == '\0') { /* user is probably trying to add "./", "/", ".." or ".", ignoring it silently */ zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; } /* copy entry.. */ entry_copy = emalloc(sizeof(archive_entry_t)); memcpy(entry_copy, entry, sizeof(archive_entry_t)); entry_copy->entry = archive_entry_new(); entry_copy->filename = estrdup(entry->filename); entry_copy->data = NULL; entry_copy->data_len = 0; archive_entry_copy_pathname(entry_copy->entry, pathname); stat_sb = archive_entry_stat(entry->entry); archive_entry_copy_stat(entry_copy->entry, stat_sb); /* ..and add it to the hash */ zend_hash_update(arch->entries, pathname, pathname_len + 1, &entry_copy, sizeof(archive_entry_t), NULL); zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; }
/* ArchiveReader::getNextEntry {{{ * */ ZEND_METHOD(ArchiveReader, getNextEntry) { zval *this = getThis(); archive_file_t *arch; int result, error_num, resource_id; const char *error_string; zend_bool fetch_entry_data = 0; archive_entry_t *entry; struct archive_entry *current_entry; size_t len; off_t offset; char *buf; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &fetch_entry_data) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (arch->struct_state == ARCHIVE_OK) { result = archive_read_next_header(arch->arch, ¤t_entry); arch->struct_state = result; entry = (archive_entry_t *) emalloc(sizeof(archive_entry_t)); entry->entry = current_entry; entry->data = NULL; entry->filename = NULL; entry->resolved_filename = NULL; entry->data_len = 0; arch->current_entry = entry; } else { zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_FALSE; } if (result && result != ARCHIVE_EOF) { arch->current_entry = NULL; error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); efree(entry); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read file %s: error #%d, %s", arch->filename, error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read file %s: unknown error %d", arch->filename, result); } zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (result == ARCHIVE_EOF) { arch->current_entry = NULL; efree(entry); zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_FALSE; } object_init_ex(return_value, ce_ArchiveEntry); if (fetch_entry_data) { while ((result = archive_read_data_block(arch->arch, (const void **)&buf, &len, &offset)) == ARCHIVE_OK) { entry->data = erealloc(entry->data, entry->data_len + len + 1); memcpy(entry->data + entry->data_len, buf, len); entry->data_len += len; } if (result && result != ARCHIVE_EOF) { error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); efree(entry); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read file %s: error #%d, %s", arch->filename, error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read file %s: unknown error %d", arch->filename, result); } zend_restore_error_handling(&error_handling TSRMLS_CC); return; } } if (entry->entry) { resource_id = zend_list_insert(entry,le_archive_entry); add_property_resource(return_value, "entry", resource_id); } zend_restore_error_handling(&error_handling TSRMLS_CC); }