zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #24293
[Merge] lp:~zorba-coders/zorba/bug-1189785-archive into lp:zorba
Chris Hillery has proposed merging lp:~zorba-coders/zorba/bug-1189785-archive into lp:zorba.
Commit message:
Update tests for new base64 module namespace URI.
Requested reviews:
Chris Hillery (ceejatec)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-1189785-archive/+merge/175212
--
https://code.launchpad.net/~zorba-coders/zorba/bug-1189785-archive/+merge/175212
Your team Zorba Coders is subscribed to branch lp:zorba.
=== added file 'CMakeLists.txt'
--- CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ CMakeLists.txt 2013-07-17 07:51:32 +0000
@@ -0,0 +1,54 @@
+# Copyright 2012 The FLWOR Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+PROJECT (zorba_archive_module)
+ENABLE_TESTING ()
+INCLUDE (CTest)
+
+IF (WIN32)
+ # On Windows we use proxy modules that try to guess first the location
+ # of the required third party libraries. This will search in order in:
+ # 1. the path pointed by ZORBA_THIRD_PARTY_REQUIREMENTS
+ # 2. the Program Files directory available on the users computer
+ # 3. the PATH environment variable
+ # The logic is implemented by the macros in the ProxyFindModule.cmake module.
+ LIST (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules/Windows")
+ENDIF (WIN32)
+LIST (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
+
+FIND_PACKAGE (Zorba REQUIRED HINTS "${ZORBA_BUILD_DIR}")
+MESSAGE(STATUS "Zorba_USE_FILE ${Zorba_USE_FILE}")
+INCLUDE ("${Zorba_USE_FILE}")
+
+IF (ZORBA_SUPPRESS_LIBARCHIVE)
+ MESSAGE (STATUS "ZORBA_SUPRESS_LIBARCHIVE is true - not searching for LibArchive.")
+ELSE (ZORBA_SUPRESS_LINARCHIVE)
+
+ MESSAGE (STATUS "Looking for LibArchive")
+ FIND_PACKAGE (LibArchive)
+
+ IF (LIBARCHIVE_FOUND)
+ MESSAGE (STATUS "Found LibArchive --" ${LIBARCHIVE_LIBRARIES})
+ INCLUDE_DIRECTORIES (${LIBARCHIVE_INCLUDE_DIR})
+
+ ADD_SUBDIRECTORY("src")
+ ADD_TEST_DIRECTORY("${PROJECT_SOURCE_DIR}/test")
+ ELSE (LIBARCHIVE_FOUND)
+ MESSAGE (STATUS "LibArchive library not found == if you want to use the archive functionality please set LIBARCHIVE_INCLUDE_DIR and LIBARCHIVE_LIBRARIES cmake parameters accordingly.")
+ ENDIF (LIBARCHIVE_FOUND)
+ENDIF (ZORBA_SUPPRESS_LIBARCHIVE)
+
+DONE_DECLARING_ZORBA_URIS()
=== renamed file 'CMakeLists.txt' => 'CMakeLists.txt.moved'
=== added directory 'cmake_modules'
=== renamed directory 'cmake_modules' => 'cmake_modules.moved'
=== added file 'cmake_modules/FindLibArchive.cmake'
--- cmake_modules/FindLibArchive.cmake 1970-01-01 00:00:00 +0000
+++ cmake_modules/FindLibArchive.cmake 2013-07-17 07:51:32 +0000
@@ -0,0 +1,48 @@
+# Copyright 2012 The FLWOR Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+IF (LIBARCHIVE_INCLUDE_DIR)
+ SET (LIBARCHIVE_FIND_QUIETLY TRUE)
+ENDIF (LIBARCHIVE_INCLUDE_DIR)
+
+FIND_PATH (
+ LIBARCHIVE_INCLUDE_DIR
+ archive.h
+ PATHS ${LIBACHIVE_INCLUDE_DIR} /usr/include/ /usr/local/include /opt/local/include )
+MARK_AS_ADVANCED (LIBARCHIVE_INCLUDE_DIR)
+
+FIND_LIBRARY (
+ LIBARCHIVE_LIBRARY
+ NAMES archive
+ PATHS ${LIBACHIVE_LIBRARY_DIR} /usr/lib /usr/local/lib /opt/local/lib)
+MARK_AS_ADVANCED (LIBARCHIVE_LIBRARY)
+
+IF (LIBARCHIVE_INCLUDE_DIR AND LIBARCHIVE_LIBRARY)
+ SET (LIBARCHIVE_FOUND 1)
+ SET (LIBARCHIVE_LIBRARIES ${LIBARCHIVE_LIBRARY})
+ SET (LIBARCHIVE_INCLUDE_DIRS ${LIBARCHIVE_INCLUDE_DIR})
+ IF (NOT LIBARCHIVE_FIND_QUIETLY)
+ MESSAGE (STATUS "Found libarchive library: " ${LIBARCHIVE_LIBRARY})
+ MESSAGE (STATUS "Found libarchive include path : " ${LIBARCHIVE_INCLUDE_DIR})
+ ENDIF (NOT LIBARCHIVE_FIND_QUIETLY)
+
+ SET(CMAKE_REQUIRED_INCLUDES "${LIBARCHIVE_INCLUDE_DIR}")
+ SET(CMAKE_REQUIRED_LIBRARIES "${LIBARCHIVE_LIBRARY}")
+ INCLUDE(CheckFunctionExists)
+ CHECK_FUNCTION_EXISTS(archive_write_zip_set_compression_deflate ZORBA_LIBARCHIVE_HAVE_SET_COMPRESSION)
+ELSE (LIBARCHIVE_INCLUDE_DIR AND LIBARCHIVE_LIBRARY)
+ SET (LIBARCHIVE_FOUND 0)
+ SET (LIBARCHIVE_LIBRARIES)
+ SET (LIBARCHIVE_INCLUDE_DIRS)
+ENDIF (LIBARCHIVE_INCLUDE_DIR AND LIBARCHIVE_LIBRARY)
=== added directory 'cmake_modules/Windows'
=== added file 'cmake_modules/Windows/FindLibArchive.cmake'
--- cmake_modules/Windows/FindLibArchive.cmake 1970-01-01 00:00:00 +0000
+++ cmake_modules/Windows/FindLibArchive.cmake 2013-07-17 07:51:32 +0000
@@ -0,0 +1,23 @@
+# Copyright 2012 The FLWOR Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FIND_PACKAGE_WIN32 (NAME LibArchive FOUND_VAR LIBARCHIVE_FOUND SEARCH_NAMES libarchive)
+
+IF (LIBARCHIVE_FOUND)
+ FIND_PACKAGE_DLLS_WIN32 (${FOUND_LOCATION} archive.dll)
+ SET(CMAKE_REQUIRED_INCLUDES "${LIBARCHIVE_INCLUDE_DIR}")
+ SET(CMAKE_REQUIRED_LIBRARIES "${LIBARCHIVE_LIBRARY}")
+ INCLUDE(CheckFunctionExists)
+ CHECK_FUNCTION_EXISTS(archive_write_zip_set_compression_deflate LIBARCHIVE_HAVE_SET_COMPRESSION)
+ENDIF (LIBARCHIVE_FOUND)
=== added directory 'src'
=== renamed directory 'src' => 'src.moved'
=== added file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/CMakeLists.txt 2013-07-17 07:51:32 +0000
@@ -0,0 +1,27 @@
+# Copyright 2012 The FLWOR Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/archive_module.xq.src/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/archive_module.xq.src/config.h")
+
+INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/archive_module.xq.src")
+
+DECLARE_ZORBA_MODULE (
+ URI "http://www.zorba-xquery.com/modules/archive"
+ VERSION 1.0
+ FILE "archive_module.xq"
+ LINK_LIBRARIES "${LIBARCHIVE_LIBRARIES}")
+
+DECLARE_ZORBA_SCHEMA (
+ URI "http://www.zorba-xquery.com/modules/archive"
+ FILE "archive.xsd")
=== added file 'src/archive.xsd'
--- src/archive.xsd 1970-01-01 00:00:00 +0000
+++ src/archive.xsd 2013-07-17 07:51:32 +0000
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.zorba-xquery.com/modules/archive"
+ xmlns="http://www.zorba-xquery.com/modules/archive"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <xs:simpleType name="compression-type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="store"/>
+ <xs:enumeration value="deflate"/>
+ <xs:enumeration value="bzip2"/>
+ <xs:enumeration value="lzma"/>
+ <xs:enumeration value="STORE"/>
+ <xs:enumeration value="DEFLATE"/>
+ <xs:enumeration value="BZIP2"/>
+ <xs:enumeration value="LZMA"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="format-type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="zip"/>
+ <xs:enumeration value="tar"/>
+ <xs:enumeration value="pax"/>
+ <xs:enumeration value="ZIP"/>
+ <xs:enumeration value="TAR"/>
+ <xs:enumeration value="PAX"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="boolean-type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="true"/>
+ <xs:enumeration value="false"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="entry-name-type">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="entry-datetime-type">
+ <xs:restriction base="xs:dateTime"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="entry-size-type">
+ <xs:restriction base="xs:short"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="entry-encoding-type">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="entry-type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="regular"/>
+ <xs:enumeration value="directory"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- elements -->
+ <xs:element name="archive-option-element"
+ abstract="true" type="xs:string"/>
+
+ <xs:element name="compression"
+ type="compression-type"
+ substitutionGroup="archive-option-element"/>
+
+ <xs:element name="format" type="format-type"
+ substitutionGroup="archive-option-element"/>
+
+ <xs:element name="skip-extra-attributes" type="boolean-type"
+ substitutionGroup="archive-option-element"/>
+
+ <xs:element name="options">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="archive-option-element"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="entry">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="entry-name-type">
+ <xs:attributeGroup ref="entry-attributes"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- entry attributes -->
+ <xs:attributeGroup name="entry-attributes">
+ <xs:attribute name="type" type="entry-type"/>
+ <xs:attribute name="size" type="entry-size-type"/>
+ <xs:attribute name="last-modified" type="entry-datetime-type"/>
+ <xs:attribute name="encoding" type="entry-encoding-type"/>
+ <xs:attribute name="compression" type="compression-type"/>
+ </xs:attributeGroup>
+
+</xs:schema>
=== added file 'src/archive_module.xq'
--- src/archive_module.xq 1970-01-01 00:00:00 +0000
+++ src/archive_module.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,302 @@
+xquery version "1.0";
+
+(:
+ : Copyright 2012 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+ :)
+
+(:~
+ : <p>This module provides functionality to work with (possibly compressed)
+ : archives. For example, it provides functions to retrieve the names or
+ : extract the values of several entries in a ZIP archive. Moreover,
+ : there exist functions that allow to create or update archives.</p>
+ :
+ : <p>The following archive formats and compression algorithms are supported:
+ : <ul>
+ : <li>ZIP (with compression DEFLATE or STORE)</li>
+ : <li>TAR (with compression GZIP)</li>
+ : </ul>
+ : </p>
+ :
+ : @author Luis Rodgriguez, Juan Zacarias, and Matthias Brantner
+ :
+ : @library <a href="http://code.google.com/p/libarchive/">libarchive</a>
+ : @project Zorba/Archive
+ :)
+module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+import schema namespace options = "http://www.zorba-xquery.com/modules/archive";
+
+declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
+declare option ver:module-version "1.0";
+
+(:~
+ : Creates a new ZIP archive out of the given entries and contents.
+ :
+ : <p>All entries are compressed with the DEFLATE compression algorithm.</p>
+ :
+ : <p>The parameters $entries and $contents have the same meaning as for
+ : the function a:create with three arguments.</p>
+ :
+ : <p>Entry entries can include a type attribute, this attribute can have one
+ : of two possible values: "regular" or "directory". If "regular" is
+ : specified then the entry will be created as a regular file; if "directory"
+ : is specified then the entry will be created as a directory, no contents
+ : will be read from $contents in this case. If no value is specified for type
+ : then it will be set to "regular". Example:
+ : <pre>
+ : $zip-file := a:create(
+ : (<a:entry encoding="ISO-8859-1" type="directory">dir1</a:entry>, "dir1/file1"),
+ : ("file contents"))
+ : </pre>
+ : </p>
+ :
+ : @param $entries the meta data for the entries in the archive. Each entry
+ : can be of type xs:string or an element with name a:entry.
+ : @param $contents the content for the archive. Each item in the sequence
+ : can be of type xs:string or xs:base64Binary.
+ :
+ : @return the generated archive as xs:base64Binary
+ :
+ : @error a:ARCH0001 if the number of entry elements differs from the number
+ : of items in the $contents sequence: count($entries) ne count($contents)
+ : @error a:ARCH0003 if a value for an entry element is invalid
+ : @error a:ARCH0004 if a given encoding is invalid or not supported
+ : @error err:FORG0006 if an item in the contents sequence is not of type xs:string
+ : or xs:base64Binary
+ :)
+declare function a:create(
+ $entries as item()*,
+ $contents as item()*)
+ as xs:base64Binary external;
+
+(:~
+ : Creates a new archive out of the given entries and contents.
+ :
+ : <p>The $entries arguments provides meta data for each entry in the archive.
+ : For example, the name of the entry (mandatory) or the last-modified date
+ : (optional). An entry can either be of type xs:string to describe the entry
+ : name or of type xs:base64Binary to provide additional meta data.</p>
+ :
+ : <p>The $contents sequence provides the data (xs:string or xs:base64Binary) for
+ : the entries that should be included in the archive. Its length needs to
+ : match the length of the $entries sequence (a:ARCH0001). All items of type
+ : xs:base64Binary are decoded before being added to the archive.</p>
+ :
+ : <p>For each entry, the name, last-modified date and time, and compression
+ : can be specified. In addition, an encoding can be specified which is used to
+ : store entries of type xs:string. If no last-modified attribute is given, the
+ : default is the current date and time. The compression is useful if various
+ : entries in a ZIP archive are compressed using different compression
+ : algorithms (i.e. store or deflate).</p>
+ :
+ : <p>For example, the following sequence may be used to describe an archive
+ : containing three elements:
+ : <pre class="ace-static" ace-mode="xquery"><![CDATA[<a:entry last-modified="{fn:current-dateTime()}">myfile.txt</a:entry>
+ : <a:entry encoding="ISO-8859-1" compression="store">dir/myfile.xml</a:entry>]]>
+ : </pre>
+ : </p>
+ :
+ : <p>The $options argument may be used to describe general options for the
+ : archive. For example, the following option element can be used to create a ZIP
+ : archive in which all entries are compressed with the DEFLATE compression
+ : algorithm:
+ : <pre class="ace-static" ace-mode="xquery"><![CDATA[<archive:options>
+ : <archive:format>ZIP</archive:format>
+ : <archive:compression>DEFLATE</archive:compression>
+ : </archive:options>]]>
+ : </pre>
+ : </p>
+ :
+ : <p>The result of the function is the generated archive as a item of type
+ : xs:base64Binary.</p>
+ :
+ :
+ : @param $entries the meta data for the entries in the archive. Each entry
+ : can be of type xs:string or an element with name a:entry.
+ : @param $contents the content for the archive. Each item in the sequence
+ : can be of type xs:string or xs:base64Binary.
+ : @param $options the options used to generate the archive.
+ :
+ : @return the generated archive as xs:base64Binary
+ :
+ : @error a:ARCH0001 if the number of entry elements differs from the number
+ : of items in the $contents sequence: count($entries) ne count($contents)
+ : @error a:ARCH0002 if the options argument contains invalid values
+ : @error a:ARCH0003 if a value for an entry element is invalid
+ : @error a:ARCH0004 if a given encoding is invalid or not supported
+ : @error err:FORG0006 if an item in the contents sequence is not of type xs:string
+ : or xs:base64Binary
+ :)
+declare function a:create(
+ $entries as item()*,
+ $contents as item()*,
+ $options as element(a:options))
+ as xs:base64Binary external;
+
+(:~
+ : Returns the header information of all entries in the given archive.
+ :
+ : <p>Such information includes the name of the entry, the uncompressed size,
+ : as well as the last-modified timestamp. Note that not all values are
+ : available in every archive.</p>
+ :
+ : @param $archive the archive to list the entries from as xs:base64Binary
+ :
+ : @return a sequence of strings, one for each entry in the archive
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ :)
+declare function a:entries($archive as xs:base64Binary)
+ as element(a:entry)* external;
+
+(:~
+ : Extracts the contents of all entries in the given archive as text
+ : using UTF-8 as default encoding.
+ :
+ : @param $archive the archive to extract the entries from as xs:base64Binary
+ :
+ : @return one string for the contents of each entry in the archive
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ : @error err:FOCH0001 if any of the entries contains invalid utf-8 characters
+ :)
+declare function a:extract-text($archive as xs:base64Binary)
+ as xs:string* external;
+
+(:~
+ : Extracts the contets of the entries identified by a given sequence of
+ : names as text.
+ : The default encoding used to read the string is UTF-8.
+ :
+ : @param $archive the archive to extract the entries from as xs:base64Binary
+ : @param $entry-names a sequence of names for entries which should be extracted
+ :
+ : @return a sequence of strings for the given sequence of names or the
+ : empty sequence if no entries match the given names.
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ : @error err:FOCH0001 if any of the entries requested contains invalid utf-8 characters
+ :)
+declare function a:extract-text($archive as xs:base64Binary, $entry-names as xs:string*)
+ as xs:string* external;
+
+(:~
+ : Extracts the contets of the entries identified by a given sequence of
+ : names as text. Each entry is treated with the given encoding.
+ :
+ : @param $archive the archive to extract the entries from as xs:base64Binary
+ : @param $entry-names a sequence of entry names that should be extracted
+ : @param $encoding a encoding for transcoding each of the extracted entries
+ :
+ : @return a sequence of strings for the given sequence of names or the
+ : empty sequence if no entries match the given names.
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ : @error a:ARCH0004 if the given $encoding is invalid or not supported
+ : @error err:FOCH0001 if a transcoding error happens
+ :)
+declare function a:extract-text(
+ $archive as xs:base64Binary,
+ $entry-names as xs:string*,
+ $encoding as xs:string)
+ as xs:string* external;
+
+(:~
+ : Returns the entries identified by the given paths from the archive
+ : as base64Binary.
+ :
+ : @param $archive the archive to extract the entries from as xs:base64Binary
+ :
+ : @return one xs:base64Binary item for the contents of each entry in the archive
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ :)
+declare function a:extract-binary($archive as xs:base64Binary)
+ as xs:base64Binary* external;
+
+(:~
+ : Returns the entries identified by the given paths from the archive
+ : as base64Binary.
+ :
+ : @param $archive the archive to extract the entries from as xs:base64Binary
+ :
+ : @param $entry-names a sequence of names for entries which should be extracted
+ :
+ : @return a sequence of xs:base64Binary itmes for the given sequence of names
+ : or the empty sequence if no entries match the given names.
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ :)
+declare function a:extract-binary($archive as xs:base64Binary, $entry-names as xs:string*)
+ as xs:base64Binary* external;
+
+(:~
+ : Adds and replaces entries in an archive according to
+ : the given spec. The contents can be string and base64Binary items.
+ :
+ : <p>The parameters $entries and $contents have the same meaning as for
+ : the function a:create with three arguments.</p>
+ :
+ : @param $archive the archive to add or replace content
+ : @param $entries the meta data for the entries in the archive. Each entry
+ : can be of type xs:string or an element with name a:entry.
+ : @param $contents the content for the archive. Each item in the sequence
+ : can be of type xs:string or xs:base64Binary.
+ :
+ : @return the updated xs:base64Binary
+ :
+ : @error a:ARCH0001 if the number of entry elements differs from the number
+ : of items in the $contents sequence: count($entries) ne count($contents)
+ : @error a:ARCH0003 if a value for an entry element is invalid
+ : @error a:ARCH0004 if a given encoding is invalid or not supported
+ : @error err:FORG0006 if an item in the contents sequence is not of type xs:string
+ : or xs:base64Binary
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ :
+ :)
+declare function a:update($archive as xs:base64Binary, $entries as item()*, $contents as item()*)
+ as xs:base64Binary external;
+
+(:~
+ : Deletes entries from an archive.
+ :
+ : @param $archive the archive to extract the entries from as xs:base64Binary
+ : @param $entry-names a sequence of names for entries which should be deleted
+ :
+ : @return the updated base64Binary
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ :)
+declare function a:delete($archive as xs:base64Binary, $entry-names as xs:string*)
+ as xs:base64Binary external;
+
+(:~
+ : Returns the algorithm and format options of the given archive.
+ : For example, for a ZIP archive, the following options element
+ : would be returned:
+ : <pre class="ace-static" ace-mode="xquery"><![CDATA[<archive:options>
+ : <archive:format>ZIP</archive:format>
+ : <archive:compressionDEFLATE</archive:compression>
+ : </archive:options>]]>
+ : </pre>
+ :
+ : @param $archive the archive as xs:base64Binary
+ :
+ : @return the algorithm and format options
+ :
+ : @error a:ARCH9999 if $archive is not an archive or corrupted
+ :)
+declare function a:options($archive as xs:base64Binary)
+ as element(a:options) external;
=== added directory 'src/archive_module.xq.src'
=== added file 'src/archive_module.xq.src/archive_module.cpp'
--- src/archive_module.xq.src/archive_module.cpp 1970-01-01 00:00:00 +0000
+++ src/archive_module.xq.src/archive_module.cpp 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1674 @@
+/*
+ * Copyright 2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <sys/types.h>
+
+#include <sys/timeb.h>
+#ifdef UNIX
+# include <sys/time.h>
+#endif
+#ifdef WIN32
+# include <strptime.h>
+# include <MMSystem.h>
+#endif
+
+#include <zorba/diagnostic_list.h>
+#include <zorba/empty_sequence.h>
+#include <zorba/item_factory.h>
+#include <zorba/singleton_item_sequence.h>
+#include <zorba/user_exception.h>
+#include <zorba/util/base64_util.h>
+#include <zorba/util/base64_stream.h>
+#include <zorba/util/transcode_stream.h>
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_module.h"
+#include "config.h"
+
+namespace zorba { namespace archive {
+
+
+/*******************************************************************************
+ ******************************************************************************/
+ zorba::ExternalFunction*
+ ArchiveModule::getExternalFunction(const zorba::String& localName)
+ {
+ FuncMap_t::iterator lIte = theFunctions.find(localName);
+
+ ExternalFunction*& lFunc = theFunctions[localName];
+
+ if (lIte == theFunctions.end())
+ {
+ if (localName == "create")
+ {
+ lFunc = new CreateFunction(this);
+ }
+ else if (localName == "entries")
+ {
+ lFunc = new EntriesFunction(this);
+ }
+ else if (localName == "extract-text")
+ {
+ lFunc = new ExtractTextFunction(this);
+ }
+ else if (localName == "extract-binary")
+ {
+ lFunc = new ExtractBinaryFunction(this);
+ }
+ else if (localName == "delete")
+ {
+ lFunc = new DeleteFunction(this);
+ }
+ else if (localName == "update")
+ {
+ lFunc = new UpdateFunction(this);
+ }
+ else if (localName == "options")
+ {
+ lFunc = new OptionsFunction(this);
+ }
+ }
+
+ return lFunc;
+ }
+
+ void ArchiveModule::destroy()
+ {
+ delete this;
+ }
+
+ ArchiveModule::~ArchiveModule()
+ {
+ for (FuncMap_t::const_iterator lIter = theFunctions.begin();
+ lIter != theFunctions.end(); ++lIter)
+ {
+ delete lIter->second;
+ }
+ theFunctions.clear();
+ }
+
+ zorba::Item
+ ArchiveModule::createDateTimeItem(time_t& aTime)
+ {
+ // create a datetime item with UTC as timezone
+ // this seems to be what mtime from libarchive returns
+ struct ::tm gmtm;
+#ifdef WIN32
+ gmtime_s(&gmtm, &aTime);
+#else
+ gmtime_r(&aTime, &gmtm);
+#endif
+
+ // create a datetime item without timezone because
+ // this is what the entry tells us (at least for zip)
+ Item lModifiedItem = getItemFactory()->createDateTime(
+ static_cast<short>(gmtm.tm_year + 1900),
+ static_cast<short>(gmtm.tm_mon + 1),
+ static_cast<short>(gmtm.tm_mday),
+ static_cast<short>(gmtm.tm_hour),
+ static_cast<short>(gmtm.tm_min),
+ gmtm.tm_sec,
+ 0);
+ return lModifiedItem;
+ }
+
+ void
+ ArchiveModule::parseDateTimeItem(const zorba::Item& i, time_t& t)
+ {
+ const char* lTime = i.getStringValue().c_str();
+
+ struct tm tm;
+ memset(&tm, 0, sizeof(struct tm));
+
+ char* lTmp = strptime(lTime, "%Y-%m-%dT%T", &tm);
+ if (lTmp != lTime + 19)
+ {
+ std::ostringstream lMsg;
+ lMsg << i.getStringValue()
+ << ": invalid value for last-modified attribute ";
+ ArchiveFunction::throwError("ARCH0003", lMsg.str().c_str());
+ }
+ }
+
+
+/*******************************************************************************
+ ****************************** ArchiveFunction ********************************
+ ******************************************************************************/
+ ArchiveFunction::ArchiveFunction(const ArchiveModule* aModule)
+ : theModule(aModule)
+ {
+ }
+
+ ArchiveFunction::~ArchiveFunction()
+ {
+ }
+
+
+ /******************
+ ** Archive Entry **
+ ******************/
+
+ ArchiveFunction::ArchiveEntry::ArchiveEntry()
+ : theEncoding("UTF-8"),
+ theEntryType(regular)
+ {
+ // use current time as a default for each entry
+#if defined (WIN32)
+ struct _timeb timebuffer;
+ _ftime_s( &timebuffer );
+#else
+ struct timeb timebuffer;
+ ftime( &timebuffer );
+#endif
+ theLastModified = timebuffer.time;
+ }
+
+ void
+ ArchiveFunction::ArchiveEntry::setValues(struct archive_entry* aEntry)
+ {
+ theEntryPath = archive_entry_pathname(aEntry);
+
+ if (archive_entry_size_is_set(aEntry))
+ {
+ theSize = (int)archive_entry_size(aEntry);
+ }
+
+ if (archive_entry_mtime_is_set(aEntry))
+ {
+ theLastModified = archive_entry_mtime(aEntry);
+ }
+ //check if it is encoded
+
+ switch(archive_entry_filetype(aEntry))
+ {
+ case AE_IFDIR: theEntryType = directory; break;
+ default: theEntryType = regular; break;
+ }
+ }
+
+ void
+ ArchiveFunction::ArchiveEntry::setValues(zorba::Item& aEntry)
+ {
+ theEntryPath = aEntry.getStringValue();
+
+ if (aEntry.isNode())
+ {
+ Item lAttr;
+
+ Iterator_t lAttrIter = aEntry.getAttributes();
+ lAttrIter->open();
+ while (lAttrIter->next(lAttr))
+ {
+ Item lAttrName;
+ lAttr.getNodeName(lAttrName);
+
+ if(lAttrName.getLocalName() == "type")
+ {
+ String filetype = lAttr.getStringValue();
+ if(filetype == "directory")
+ {
+ theEntryType = directory;
+ }
+ }
+ else if (lAttrName.getLocalName() == "last-modified")
+ {
+ ArchiveModule::parseDateTimeItem(lAttr, theLastModified);
+ }
+ else if (lAttrName.getLocalName() == "encoding")
+ {
+ theEncoding = lAttr.getStringValue();
+ std::transform(
+ theEncoding.begin(), theEncoding.end(),
+ theEncoding.begin(), ::toupper);
+ if (!transcode::is_supported(theEncoding.c_str()))
+ {
+ std::ostringstream lMsg;
+ lMsg << theEncoding << ": unsupported encoding";
+
+ throwError("ARCH0004", lMsg.str().c_str());
+ }
+ }
+ else if (lAttrName.getLocalName() == "compression")
+ {
+ theCompression = lAttr.getStringValue();
+ std::transform(
+ theCompression.begin(),
+ theCompression.end(),
+ theCompression.begin(), ::toupper);
+ }
+ }
+ }
+ }
+
+ /********************
+ ** Archive Options **
+ ********************/
+
+ ArchiveFunction::ArchiveOptions::ArchiveOptions()
+ : theCompression("DEFLATE"),
+ theFormat("ZIP"),
+ theSkipExtraAttrs(false)
+ {}
+
+ void
+ ArchiveFunction::ArchiveOptions::setValues(struct archive* aArchive)
+ {
+ theCompression = ArchiveFunction::compressionName(
+ archive_compression(aArchive));
+ theFormat = ArchiveFunction::formatName(archive_format(aArchive));
+ }
+
+ void
+ ArchiveFunction::ArchiveOptions::setValues(Item& aOptions)
+ {
+ Item lOption;
+
+ Iterator_t lOptionIter = aOptions.getChildren();
+ lOptionIter->open();
+
+ while (lOptionIter->next(lOption))
+ {
+ Item lOptionName;
+ lOption.getNodeName(lOptionName);
+
+ if (lOptionName.getLocalName() == "compression")
+ {
+ theCompression = lOption.getStringValue().c_str();
+ std::transform(
+ theCompression.begin(),
+ theCompression.end(),
+ theCompression.begin(), ::toupper);
+ }
+ else if (lOptionName.getLocalName() == "format")
+ {
+ theFormat = lOption.getStringValue().c_str();
+ std::transform(
+ theFormat.begin(),
+ theFormat.end(),
+ theFormat.begin(), ::toupper);
+ }
+ else if (lOptionName.getLocalName() == "skip-extra-attributes")
+ {
+ theSkipExtraAttrs = lOption.getStringValue() == "true" ? true : false;
+ }
+ }
+ if (theFormat == "ZIP")
+ {
+ if (theCompression != "STORE" && theCompression != "DEFLATE" && theCompression != "NONE")
+ {
+ std::ostringstream lMsg;
+ lMsg
+ << theCompression
+ << ": compression algorithm not supported for ZIP format (required: deflate, store)";
+ throwError("ARCH0002", lMsg.str().c_str());
+ }
+ }
+ if (theFormat == "TAR")
+ {
+ if (theCompression != "GZIP"
+#ifndef WIN32
+ && theCompression != "BZIP2"
+ && theCompression != "LZMA"
+#endif
+ )
+ {
+ std::ostringstream lMsg;
+ lMsg
+ << theCompression
+ << ": compression algorithm not supported for TAR format (required: gzip"
+#ifndef WIN32
+ << ", bzip2, lzma"
+#endif
+ << ")";
+ throwError("ARCH0002", lMsg.str().c_str());
+ }
+ }
+ }
+
+ /************************
+ ** Archive Compressor ***
+ ************************/
+
+ ArchiveFunction::ArchiveCompressor::ArchiveCompressor()
+ : theArchive(0),
+ theEntry(0),
+ theStream(new std::stringstream())
+ {
+ theEntry = archive_entry_new();
+ }
+
+ ArchiveFunction::ArchiveCompressor::~ArchiveCompressor()
+ {
+ archive_entry_free(theEntry);
+ }
+
+ void
+ ArchiveFunction::ArchiveCompressor::setOptions(const ArchiveOptions& aOptions)
+ {
+ theOptions = aOptions;
+
+ int lFormatCode = formatCode(aOptions.getFormat().c_str());
+ int lErr = archive_write_set_format(theArchive, lFormatCode);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+
+ int lCompressionCode = compressionCode(aOptions.getCompression().c_str());
+ setArchiveCompression(theArchive, lCompressionCode);
+
+ if (aOptions.getSkipExtraAttrs())
+ {
+ // ignore result value because some libarchive versions
+ // don't support this option
+ archive_write_set_options(theArchive, "zip:skip-extras=true");
+ }
+
+ lErr = archive_write_open(
+ theArchive, this, 0, ArchiveFunction::writeStream, 0);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+
+ bool
+ ArchiveFunction::ArchiveCompressor::getStreamForString(
+ const zorba::String& aEncoding,
+ zorba::Item& aFile,
+ std::istream*& aResStream,
+ uint64_t& aResFileSize) const
+ {
+ // 1. always need to materialize if transcoding is necessary
+ // or stream is not seekable to compute resulting file size
+ if (aFile.isStreamable() &&
+ (!aFile.isSeekable() ||
+ transcode::is_necessary(aEncoding.c_str())))
+ {
+ aResStream = &aFile.getStream();
+
+ if (transcode::is_necessary(aEncoding.c_str()))
+ {
+ transcode::attach(*aResStream, aEncoding.c_str());
+ }
+
+ std::stringstream* lStream = new std::stringstream();
+
+ char lBuf[ZORBA_ARCHIVE_MAX_READ_BUF];
+ while (aResStream->good())
+ {
+ aResStream->read(lBuf, ZORBA_ARCHIVE_MAX_READ_BUF);
+ lStream->write(lBuf, aResStream->gcount());
+ aResFileSize += aResStream->gcount();
+ }
+ aResStream = lStream;
+ return true; // delete after use
+ }
+ // 2. seekable and no transcoding is best cast
+ // => compute size by seeking and return stream as-is
+ else if (aFile.isStreamable())
+ {
+ aResStream = &aFile.getStream();
+
+ aResStream->seekg(0, std::ios::end);
+ aResFileSize = aResStream->tellg();
+ aResStream->seekg(0, std::ios::beg);
+ return false;
+ }
+ // 3. non-streamable string
+ else
+ {
+ std::stringstream* lStream = new std::stringstream();
+
+ // 3.1 with transcoding
+ if (transcode::is_necessary(aEncoding.c_str()))
+ {
+ transcode::stream<std::istringstream> lTranscoder(
+ aEncoding.c_str(),
+ aFile.getStringValue().c_str()
+ );
+ char lBuf[ZORBA_ARCHIVE_MAX_READ_BUF];
+ while (lTranscoder.good())
+ {
+ lTranscoder.read(lBuf, ZORBA_ARCHIVE_MAX_READ_BUF);
+ lStream->write(lBuf, lTranscoder.gcount());
+ aResFileSize += lTranscoder.gcount();
+ }
+ }
+ else // 3.2 without transcoding
+ {
+ zorba::String lString = aFile.getStringValue();
+ aResFileSize = lString.length();
+ lStream->write(lString.c_str(), aResFileSize);
+ }
+ aResStream = lStream;
+ return true;
+ }
+ }
+
+ bool
+ ArchiveFunction::ArchiveCompressor::getStreamForBase64(
+ zorba::Item& aFile,
+ std::istream*& aResStream,
+ uint64_t& aResFileSize) const
+ {
+ if (aFile.isStreamable() && aFile.isSeekable())
+ {
+ aResStream = &aFile.getStream();
+
+ aResStream->seekg(0, std::ios::end);
+ aResFileSize = aResStream->tellg();
+ aResStream->seekg(0, std::ios::beg);
+
+ if (aFile.isEncoded())
+ {
+ base64::attach(*aResStream);
+ // compute the size of the stream after base64 decoding
+ aResFileSize = ((aResFileSize / 4) + !!(aResFileSize % 4)) * 3;
+ }
+ return false;
+ }
+ else
+ {
+ std::stringstream* lStream = new std::stringstream();
+
+ size_t lResFileSize;
+ const char* lBinValue = aFile.getBase64BinaryValue(lResFileSize);
+
+ if (aFile.isEncoded())
+ {
+ zorba::String lEncoded(lBinValue, lResFileSize);
+ zorba::String lDecoded = zorba::base64::decode(lEncoded);
+ lStream->write(lDecoded.c_str(), lDecoded.length());
+ aResFileSize = lDecoded.size();
+ }
+ else
+ {
+ lStream->write(lBinValue, lResFileSize);
+ aResFileSize = lResFileSize;
+ }
+ aResStream = lStream;
+ return true;
+ }
+ }
+
+ bool
+ ArchiveFunction::ArchiveCompressor::getStream(
+ const ArchiveEntry& aEntry,
+ zorba::Item& aFile,
+ std::istream*& aResStream,
+ uint64_t& aResFileSize) const
+ {
+ aResFileSize = 0;
+
+ switch (aFile.getTypeCode())
+ {
+ case store::XS_STRING:
+ {
+ const zorba::String& lEncoding = aEntry.getEncoding();
+
+ return getStreamForString(lEncoding, aFile, aResStream, aResFileSize);
+ }
+ case store::XS_BASE64BINARY:
+ {
+ return getStreamForBase64(aFile, aResStream, aResFileSize);
+ }
+ default:
+ {
+ String errNS("http://www.w3.org/2005/xqt-errors");
+ Item errQName = ArchiveModule::getItemFactory()->createQName(
+ errNS, "FORG0006");
+ std::ostringstream lMsg;
+ lMsg << aFile.getType().getStringValue()
+ << ": invalid content argument "
+ << "(xs:string or xs:base64binary)";
+ throw USER_EXCEPTION(errQName, lMsg.str());
+ }
+ }
+
+ }
+
+ void
+ ArchiveFunction::ArchiveCompressor::open(
+ const ArchiveOptions& aOptions)
+ {
+ theArchive = archive_write_new();
+
+ if (!theArchive)
+ ArchiveFunction::throwError(
+ "ARCH9999", "internal error (couldn't create archive)");
+
+ setOptions(aOptions);
+ }
+
+ void
+ ArchiveFunction::ArchiveCompressor::compress(
+ const std::vector<ArchiveEntry>& aEntries,
+ zorba::Iterator_t& aFiles)
+ {
+ zorba::Item lFile;
+ aFiles->open();
+
+ for (size_t i = 0; i < aEntries.size(); ++i)
+ {
+ if(aEntries[i].getEntryType() == ArchiveEntry::regular)
+ {
+ if (!aFiles->next(lFile))
+ {
+ std::ostringstream lMsg;
+ lMsg << "number of entries (" << aEntries.size()
+ << ") doesn't match number of content arguments (" << i << ")";
+ throwError("ARCH0001", lMsg.str().c_str());
+ }
+ }
+
+ const ArchiveEntry& lEntry = aEntries[i];
+
+ compress(lEntry, lFile);
+
+ }
+
+ if (aFiles->next(lFile))
+ {
+ std::ostringstream lMsg;
+ lMsg << "number of entries (" << aEntries.size()
+ << ") less than number of content arguments";
+ throwError("ARCH0001", lMsg.str().c_str());
+ }
+
+ aFiles->close();
+ }
+
+ void ArchiveFunction::ArchiveCompressor::compress(const ArchiveEntry& aEntry, Item aFile)
+ {
+ std::istream* lStream;
+ bool lDeleteStream;
+ uint64_t lFileSize;
+
+ archive_entry_set_pathname(theEntry, aEntry.getEntryPath().c_str());
+ archive_entry_set_mtime(theEntry, aEntry.getLastModified(), 0);
+ // TODO: modified to allow the creation of empty directories
+ if(aEntry.getEntryType() == ArchiveEntry::regular){
+ archive_entry_set_filetype(theEntry, AE_IFREG);
+ lDeleteStream = getStream(
+ aEntry, aFile, lStream, lFileSize);
+ } else {
+ archive_entry_set_filetype(theEntry, AE_IFDIR);
+ lDeleteStream = false;
+ lFileSize = 0;
+ }
+ // TODO: specifies the permits of a file
+ archive_entry_set_perm(theEntry, 0644);
+ archive_entry_set_size(theEntry, lFileSize);
+
+ if (theOptions.getFormat() == "ZIP")
+ {
+ int lNextComp;
+ std::string lNextCompString;
+ if (aEntry.getCompression().length() > 0)
+ {
+ lNextCompString = aEntry.getCompression().c_str();
+ lNextComp = compressionCode(lNextCompString);
+#ifndef ZORBA_LIBARCHIVE_HAVE_SET_COMPRESSION
+ std::ostringstream lMsg;
+ lMsg << lNextCompString << ": setting different compression algorithms for each entry is not supported by the used version of libarchive";
+ throwError("ARCH0099", lMsg.str().c_str());
+#endif
+ }
+ else
+ {
+ lNextCompString = theOptions.getCompression();
+ lNextComp = compressionCode(lNextCompString);
+ }
+ if (lNextComp < ZORBA_ARCHIVE_COMPRESSION_DEFLATE && lNextComp != ARCHIVE_COMPRESSION_NONE)
+ {
+ std::ostringstream lMsg;
+ lMsg << lNextCompString << ": compression algorithm not supported for ZIP format (required: deflate, store)";
+ throwError("ARCH0002", lMsg.str().c_str());
+ }
+
+#ifdef ZORBA_LIBARCHIVE_HAVE_SET_COMPRESSION
+ setArchiveCompression(theArchive, lNextComp);
+#endif
+ }
+ else
+ {
+ if (aEntry.getCompression().length() > 0)
+ {
+ std::ostringstream lMsg;
+ lMsg << aEntry.getCompression() << ": compression attribute only allowed for zip format";
+ throwError("ARCH0099", lMsg.str().c_str());
+ }
+ }
+
+ archive_write_header(theArchive, theEntry);
+
+ if(aEntry.getEntryType() == ArchiveEntry::regular)
+ {
+ char lBuf[ZORBA_ARCHIVE_MAX_READ_BUF];
+ while (lStream->good())
+ {
+ lStream->read(lBuf, ZORBA_ARCHIVE_MAX_READ_BUF);
+ archive_write_data(theArchive, lBuf, lStream->gcount());
+ }
+ }
+
+ archive_entry_clear(theEntry);
+ archive_write_finish_entry(theArchive);
+
+ if (lDeleteStream)
+ {
+ delete lStream;
+ lStream = 0;
+ }
+ }
+
+ void
+ ArchiveFunction::ArchiveCompressor::close()
+ {
+ archive_write_close(theArchive);
+ archive_write_finish(theArchive);
+ }
+
+ std::stringstream*
+ ArchiveFunction::ArchiveCompressor::getResultStream()
+ {
+ return theStream;
+ }
+
+
+ String
+ ArchiveFunction::getURI() const
+ {
+ return theModule->getURI();
+ }
+
+ void
+ ArchiveFunction::throwError(
+ const char* aLocalName,
+ const char* aErrorMessage)
+ {
+ String errNS(ArchiveModule::getModuleURI());
+ Item errQName = ArchiveModule::getItemFactory()->createQName(
+ errNS, aLocalName);
+ throw USER_EXCEPTION(errQName, aErrorMessage);
+ }
+
+ void
+ ArchiveFunction::checkForError(
+ int aErrNo,
+ const char* aLocalName,
+ struct archive *a)
+ {
+ if (aErrNo != ARCHIVE_OK)
+ {
+ if (!aLocalName)
+ {
+ throwError("ARCH9999", archive_error_string(a));
+ }
+ else
+ {
+ throwError(aLocalName, archive_error_string(a));
+ }
+ }
+ }
+
+ zorba::Item
+ ArchiveFunction::getOneItem(const Arguments_t& aArgs, int aIndex)
+ {
+ Item lItem;
+ Iterator_t args_iter = aArgs[aIndex]->getIterator();
+ args_iter->open();
+ args_iter->next(lItem);
+ args_iter->close();
+
+ return lItem;
+ }
+
+ std::string
+ ArchiveFunction::formatName(int f)
+ {
+ // first 16 bit indicate the format family
+ switch (f & ARCHIVE_FORMAT_BASE_MASK)
+ {
+ case ARCHIVE_FORMAT_TAR: return "TAR";
+ case ARCHIVE_FORMAT_ZIP: return "ZIP";
+ default: return "";
+ }
+ }
+
+ std::string
+ ArchiveFunction::compressionName(int c)
+ {
+ switch (c)
+ {
+ case ARCHIVE_COMPRESSION_NONE: return "NONE";
+ case ZORBA_ARCHIVE_COMPRESSION_DEFLATE: return "DEFLATE";
+ case ZORBA_ARCHIVE_COMPRESSION_STORE: return "STORE";
+ case ARCHIVE_COMPRESSION_GZIP: return "GZIP";
+ case ARCHIVE_COMPRESSION_BZIP2: return "BZIP2";
+ case ARCHIVE_COMPRESSION_LZMA: return "LZMA";
+ default: return "";
+ }
+ }
+
+ int
+ ArchiveFunction::formatCode(const std::string& f)
+ {
+ if (f == "TAR")
+ {
+ return ARCHIVE_FORMAT_TAR_USTAR;
+ }
+ else if (f == "ZIP")
+ {
+ return ARCHIVE_FORMAT_ZIP;
+ }
+ else
+ {
+ std::ostringstream lMsg;
+ lMsg << f << ": archive format not supported";
+ throwError("ARCH0002", lMsg.str().c_str());
+ }
+ return 0;
+ }
+
+ int
+ ArchiveFunction::compressionCode(const std::string& c)
+ {
+ if (c == "NONE")
+ {
+ return ARCHIVE_COMPRESSION_NONE;
+ }
+ else if (c == "STORE")
+ {
+ return ZORBA_ARCHIVE_COMPRESSION_STORE;
+ }
+ else if (c == "DEFLATE")
+ {
+ return ZORBA_ARCHIVE_COMPRESSION_DEFLATE;
+ }
+ else if (c == "GZIP")
+ {
+ return ARCHIVE_COMPRESSION_GZIP;
+ }
+ else if (c == "BZIP2")
+ {
+ return ARCHIVE_COMPRESSION_BZIP2;
+ }
+ else if (c == "LZMA")
+ {
+ return ARCHIVE_COMPRESSION_LZMA;
+ }
+ else
+ {
+ std::ostringstream lMsg;
+ lMsg << c << ": compression algorithm not supported";
+ throwError("ARCH0002", lMsg.str().c_str());
+ }
+ return 0;
+ }
+
+ void
+ ArchiveFunction::setArchiveCompression(struct archive* a, int c)
+ {
+ int lErr = 0;
+ switch (c)
+ {
+#ifdef ZORBA_LIBARCHIVE_HAVE_SET_COMPRESSION
+ case ZORBA_ARCHIVE_COMPRESSION_STORE:
+ lErr = archive_write_zip_set_compression_store(a); break;
+ case ZORBA_ARCHIVE_COMPRESSION_DEFLATE:
+ case ARCHIVE_COMPRESSION_NONE:
+ lErr = archive_write_zip_set_compression_deflate(a); break;
+#else
+ case ZORBA_ARCHIVE_COMPRESSION_STORE:
+ archive_write_set_options(a, "zip:compression=store");
+ break;
+ case ZORBA_ARCHIVE_COMPRESSION_DEFLATE:
+ archive_write_set_options(a, "zip:compression=deflate");
+ break;
+ case ARCHIVE_COMPRESSION_NONE:
+ lErr = archive_write_set_compression_none(a); break;
+#endif
+ case ARCHIVE_COMPRESSION_GZIP:
+ lErr = archive_write_set_compression_gzip(a); break;
+ case ARCHIVE_COMPRESSION_BZIP2:
+ lErr = archive_write_set_compression_bzip2(a); break;
+ case ARCHIVE_COMPRESSION_LZMA:
+ lErr = archive_write_set_compression_lzma(a); break;
+ default: assert(false);
+ }
+ ArchiveFunction::checkForError(lErr, 0, a);
+ }
+
+#ifdef WIN32
+ long
+#else
+ ssize_t
+#endif
+ ArchiveItemSequence::readStream(struct archive*, void *data, const void **buff)
+ {
+ ArchiveItemSequence::CallbackData* lData =
+ reinterpret_cast<ArchiveItemSequence::CallbackData*>(data);
+
+ if (lData->theEnd) return 0;
+
+ std::istream* lStream = lData->theStream;
+
+ // seek to where we left of
+ if (lData->theSeekable) lStream->seekg(lData->thePos, std::ios::beg);
+
+ lStream->read(lData->theBuffer, ZORBA_ARCHIVE_MAX_READ_BUF);
+ *buff = lData->theBuffer;
+
+ if (lStream->eof()) lData->theEnd = true;
+
+ // remember the stream pos before leaving the function
+ if (lData->theSeekable) lData->thePos = lStream->tellg();
+
+ return lStream->gcount();
+ }
+
+ ArchiveItemSequence::ArchiveIterator::ArchiveIterator(zorba::Item& a)
+ : theArchiveItem(a),
+ theArchive(0),
+ theFactory(Zorba::getInstance(0)->getItemFactory())
+ {}
+
+ void
+ ArchiveItemSequence::ArchiveIterator::open()
+ {
+ // open archive and allow for all kinds of formats and compression algos
+ theArchive = archive_read_new();
+
+ if (!theArchive)
+ ArchiveFunction::throwError(
+ "ARCH9999", "internal error (couldn't create archive)");
+
+ int lErr = archive_read_support_compression_all(theArchive);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+
+ archive_read_support_format_all(theArchive);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+
+ if (theArchiveItem.isStreamable())
+ {
+ theData.theStream = &theArchiveItem.getStream();
+ theData.theStream->clear();
+ theData.theSeekable = theArchiveItem.isSeekable();
+ theData.theEnd = false;
+ theData.thePos = 0;
+
+ if (theArchiveItem.isEncoded())
+ {
+ base64::attach(*theData.theStream);
+ }
+
+ lErr = archive_read_open(theArchive, &theData, NULL, ArchiveItemSequence::readStream, NULL);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+ else
+ {
+ size_t lLen = 0;
+ char* lData = const_cast<char*>(
+ theArchiveItem.getBase64BinaryValue(lLen));
+
+ if (theArchiveItem.isEncoded())
+ {
+ zorba::String lEncoded(lData, lLen);
+ theDecodedData = base64::decode(lEncoded);
+ lLen = theDecodedData.size();
+ lErr = archive_read_open_memory(theArchive,
+ const_cast<char*>(theDecodedData.c_str()), lLen);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+ else
+ {
+ lErr = archive_read_open_memory(theArchive, lData, lLen);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+
+ }
+ }
+
+ void
+ ArchiveItemSequence::ArchiveIterator::close()
+ {
+ int lErr = archive_read_finish(theArchive);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ theArchive = 0;
+ }
+
+#ifdef WIN32
+ long
+#else
+ ssize_t
+#endif
+ ArchiveFunction::writeStream(
+ struct archive *,
+ void *func,
+ const void *buff,
+ size_t n)
+ {
+ ArchiveFunction::ArchiveCompressor* lFunc =
+ static_cast<ArchiveFunction::ArchiveCompressor*>(func);
+
+ const char * lBuf = static_cast<const char *>(buff);
+ lFunc->getResultStream()->write(lBuf, n);
+
+ return n;
+ }
+
+/*******************************************************************************
+ ******************************************************************************/
+ zorba::ItemSequence_t
+ CreateFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ std::vector<ArchiveEntry> lEntries;
+
+ {
+ Iterator_t lEntriesIter = aArgs[0]->getIterator();
+
+ zorba::Item lEntry;
+ lEntriesIter->open();
+ while (lEntriesIter->next(lEntry))
+ {
+ lEntries.resize(lEntries.size() + 1);
+ lEntries.back().setValues(lEntry);
+ }
+ lEntriesIter->close();
+ }
+
+ ArchiveOptions lOptions;
+
+ if (aArgs.size() == 3)
+ {
+ zorba::Item lOptionsItem = getOneItem(aArgs, 2);
+ lOptions.setValues(lOptionsItem);
+ }
+
+ ArchiveCompressor lArchive;
+
+ zorba::Iterator_t lFileIter = aArgs[1]->getIterator();
+ lArchive.open(lOptions);
+ lArchive.compress(lEntries, lFileIter);
+ lArchive.close();
+
+ zorba::Item lRes = theModule->getItemFactory()->
+ createStreamableBase64Binary(
+ *lArchive.getResultStream(),
+ &(ArchiveFunction::ArchiveCompressor::releaseStream),
+ true, // seekable
+ false // not encoded
+ );
+ return ItemSequence_t(new SingletonItemSequence(lRes));
+ }
+
+
+/*******************************************************************************
+ ******************************************************************************/
+ zorba::ItemSequence_t
+ EntriesFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ Item lArchive = getOneItem(aArgs, 0);
+
+ return ItemSequence_t(new EntriesItemSequence(lArchive));
+ }
+
+ EntriesFunction::EntriesItemSequence::EntriesIterator::EntriesIterator(
+ zorba::Item& aArchive)
+ : ArchiveIterator(aArchive)
+ {
+ theUntypedQName = theFactory->createQName(
+ "http://www.w3.org/2001/XMLSchema", "untyped");
+
+ theEntryName = theFactory->createQName(
+ ArchiveModule::getModuleURI(), "entry");
+
+ theLastModifiedName = theFactory->createQName("", "last-modified");
+ theUncompressedSizeName = theFactory->createQName("", "size");
+ theEntryType = theFactory->createQName("", "type");
+ }
+
+ bool
+ EntriesFunction::EntriesItemSequence::EntriesIterator::next(zorba::Item& aRes)
+ {
+ struct archive_entry *lEntry;
+
+ int lErr = archive_read_next_header(theArchive, &lEntry);
+
+ if (lErr == ARCHIVE_EOF) return false;
+
+ if (lErr != ARCHIVE_OK)
+ {
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+
+ Item lNoParent;
+
+ Item lType = theUntypedQName;
+
+ // create entry element
+ aRes = theFactory->createElementNode(
+ lNoParent, theEntryName, lType, true, false, NsBindings());
+
+ // create text content (i.e. path name)
+ String lName = archive_entry_pathname(lEntry);
+ Item lNameItem = theFactory->createString(lName);
+ theFactory->assignElementTypedValue(aRes, lNameItem);
+
+ // create size attr if the value is set in the archive
+ if (archive_entry_size_is_set(lEntry))
+ {
+ long long lSize = archive_entry_size(lEntry);
+ Item lSizeItem = theFactory->createInteger(lSize);
+ lType = theUntypedQName;
+ theFactory->createAttributeNode(
+ aRes, theUncompressedSizeName, lType, lSizeItem);
+ }
+
+ // create last-modified attr if the value is set in the archive
+ if (archive_entry_mtime_is_set(lEntry))
+ {
+ time_t lTime = archive_entry_mtime(lEntry);
+ Item lModifiedItem = ArchiveModule::createDateTimeItem(lTime);
+
+ lType = theUntypedQName;
+ theFactory->createAttributeNode(
+ aRes, theLastModifiedName, lType, lModifiedItem);
+ }
+
+ Item lEntryType;
+ if(archive_entry_filetype(lEntry) == AE_IFDIR)
+ {
+ // this entry is a directory
+ lEntryType = theFactory->createString("directory");
+ }
+ else if(archive_entry_filetype(lEntry) == AE_IFREG)
+ {
+ lEntryType = theFactory->createString("regular");
+ }
+ else
+ {
+ // error! type not supported!
+ // for the time being don't do anything
+ }
+
+ lType = theUntypedQName;
+ theFactory->createAttributeNode(
+ aRes, theEntryType, lType, lEntryType);
+
+ // skip to the next entry and raise an error if that fails
+ lErr = archive_read_data_skip(theArchive);
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+
+ return true;
+ }
+
+/*******************************************************************************
+ ******************************************************************************/
+
+ /*******************************************************************************
+ * This function is meant to replace all the look for specific headers that are
+ * or are not in a list (ArchiveEntrySet)
+ ******************************************************************************/
+ struct archive_entry*
+ ExtractFunction::ExtractItemSequence::ExtractIterator::lookForHeader(
+ bool aMatch,
+ ArchiveOptions* aOptions)
+ {
+ struct archive_entry *lEntry = 0;
+
+ while (true)
+ {
+ int lErr = archive_read_next_header(theArchive, &lEntry);
+
+ if (lErr == ARCHIVE_EOF) return NULL;
+
+ if (lErr != ARCHIVE_OK)
+ {
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+
+ if(aOptions)
+ aOptions->setValues(theArchive);
+
+ if (theReturnAll) break;
+
+ String lName = archive_entry_pathname(lEntry);
+ if(aMatch) {
+ if (theEntryNames.find(lName.str()) != theEntryNames.end())
+ {
+ break;
+ }
+ } else {
+ if (theEntryNames.find(lName.str()) == theEntryNames.end())
+ {
+ break;
+ }
+ }
+ }
+
+ return lEntry;
+ }
+
+ zorba::ItemSequence_t
+ ExtractTextFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ Item lArchive = getOneItem(aArgs, 0);
+
+ zorba::String lEncoding("UTF-8");
+ if (aArgs.size() == 3)
+ {
+ zorba::Item lItem = getOneItem(aArgs, 2);
+ lEncoding = lItem.getStringValue();
+ if (!transcode::is_supported(lEncoding.c_str()))
+ {
+ std::ostringstream lMsg;
+ lMsg << lEncoding << ": unsupported encoding";
+
+ throwError("ARCH0004", lMsg.str().c_str());
+ }
+ }
+
+ // return all entries if no second arg is given
+ bool lReturnAll = aArgs.size() == 1;
+
+ std::auto_ptr<ExtractItemSequence> lSeq(
+ new ExtractTextItemSequence(lArchive, lReturnAll, lEncoding));
+
+ // get the names of all entries that should be retruned
+ if (aArgs.size() > 1)
+ {
+ ExtractFunction::ExtractItemSequence::EntryNameSet& lSet
+ = lSeq->getNameSet();
+
+ zorba::Item lItem;
+ Iterator_t lIter = aArgs[1]->getIterator();
+ lIter->open();
+ while (lIter->next(lItem))
+ {
+ lSet.insert(lItem.getStringValue().str());
+ }
+
+ lIter->close();
+ }
+
+ return ItemSequence_t(lSeq.release());
+ }
+
+ bool
+ ExtractTextFunction::ExtractTextItemSequence::ExtractTextIterator::next(
+ zorba::Item& aRes)
+ {
+ struct archive_entry *lEntry = lookForHeader(true);
+
+ //NULL is EOF
+ if (!lEntry)
+ return false;
+
+ String lResult;
+
+ // reserve some space if we know the decompressed size
+ if (archive_entry_size_is_set(lEntry))
+ {
+ long long lSize = archive_entry_size(lEntry);
+ lResult.reserve(lSize);
+ }
+
+ char lBuf[ZORBA_ARCHIVE_MAX_READ_BUF];
+
+ // read entire entry into a string
+ while (true)
+ {
+ int s = archive_read_data(
+ theArchive, &lBuf, ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ if (s == 0) break;
+
+ lResult.append(lBuf, s);
+ }
+
+ if (transcode::is_necessary(theEncoding.c_str()))
+ {
+ zorba::String lTranscodedString;
+ transcode::stream<std::istringstream> lTranscoder(
+ theEncoding.c_str(),
+ lResult.c_str()
+ );
+ char buf[1024];
+ while (lTranscoder.good())
+ {
+ lTranscoder.read(buf, 1024);
+ lTranscodedString.append(buf, lTranscoder.gcount());
+ }
+ aRes = theFactory->createString(lTranscodedString);
+ }
+ else
+ {
+ aRes = theFactory->createString(lResult);
+ }
+
+ return true;
+ }
+
+/*******************************************************************************
+ ******************************************************************************/
+ zorba::ItemSequence_t
+ ExtractBinaryFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ Item lArchive = getOneItem(aArgs, 0);
+
+ // return all entries if no second arg is given
+ bool lReturnAll = aArgs.size() == 1;
+
+ std::auto_ptr<ExtractItemSequence> lSeq(
+ new ExtractBinaryItemSequence(lArchive, lReturnAll));
+
+ // get the names of all entries that should be retruned
+ if (aArgs.size() > 1)
+ {
+ ExtractFunction::ExtractItemSequence::EntryNameSet& lSet
+ = lSeq->getNameSet();
+
+ zorba::Item lItem;
+ Iterator_t lIter = aArgs[1]->getIterator();
+ lIter->open();
+ while (lIter->next(lItem))
+ {
+ lSet.insert(lItem.getStringValue().str());
+ }
+
+ lIter->close();
+ }
+
+ return ItemSequence_t(lSeq.release());
+ }
+
+ bool
+ ExtractBinaryFunction::ExtractBinaryItemSequence::ExtractBinaryIterator::next(
+ zorba::Item& aRes)
+ {
+ struct archive_entry *lEntry = lookForHeader(true);
+
+ //NULL is EOF
+ if (!lEntry)
+ return false;
+
+ std::vector<unsigned char> lResult;
+
+ // reserve some space if we know the decompressed size
+ if (archive_entry_size_is_set(lEntry))
+ {
+ long long lSize = archive_entry_size(lEntry);
+ lResult.reserve(lSize);
+ }
+
+ std::vector<unsigned char> lBuf;
+ lBuf.resize(ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ // read entire entry into a string
+ while (true)
+ {
+ int s = archive_read_data(
+ theArchive, &lBuf[0], ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ if (s == 0) break;
+
+ lResult.insert(lResult.end(), lBuf.begin(), lBuf.begin() + s);
+ }
+
+ aRes = theFactory->createBase64Binary(reinterpret_cast<char const*>(&lResult[0]), lResult.size(), false);
+
+ return true;
+ }
+
+
+/*******************************************************************************
+ ******************************************************************************/
+ zorba::ItemSequence_t
+ OptionsFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ Item lArchive = getOneItem(aArgs, 0);
+
+ return ItemSequence_t(new OptionsItemSequence(lArchive));
+ }
+
+ bool
+ OptionsFunction::OptionsItemSequence::OptionsIterator::next(
+ zorba::Item& aRes)
+ {
+ if (lExhausted) return false;
+
+ lExhausted = true;
+
+ struct archive_entry *lEntry;
+
+ // to get the format, we need to peek into the first header
+ int lErr = archive_read_next_header(theArchive, &lEntry);
+
+ if (lErr != ARCHIVE_OK && lErr != ARCHIVE_EOF)
+ {
+ ArchiveFunction::checkForError(lErr, 0, theArchive);
+ }
+
+ std::string lFormat =
+ ArchiveFunction::formatName(archive_format(theArchive));
+ std::string lCompression =
+ ArchiveFunction::compressionName(archive_compression(theArchive));
+
+ if (lFormat == "ZIP")
+ {
+ lCompression = "DEFLATE";
+ }
+
+ zorba::Item lUntypedQName = theFactory->createQName(
+ "http://www.w3.org/2001/XMLSchema", "untyped");
+ zorba::Item lTmpQName = lUntypedQName;
+
+ zorba::Item lOptionsQName = theFactory->createQName(
+ ArchiveModule::getModuleURI(), "options");
+
+ zorba::Item lFormatQName = theFactory->createQName(
+ ArchiveModule::getModuleURI(), "format");
+
+ zorba::Item lCompressionQName = theFactory->createQName(
+ ArchiveModule::getModuleURI(), "compression");
+
+ zorba::Item lNoParent;
+ aRes = theFactory->createElementNode(
+ lNoParent, lOptionsQName, lTmpQName, true, false, NsBindings());
+
+ lTmpQName = lUntypedQName;
+ zorba::Item lFormatItem = theFactory->createElementNode(
+ aRes, lFormatQName, lTmpQName, true, false, NsBindings());
+
+ lTmpQName = lUntypedQName;
+ zorba::Item lCompressionItem = theFactory->createElementNode(
+ aRes, lCompressionQName, lTmpQName, true, false, NsBindings());
+
+ theFactory->createTextNode(lFormatItem, lFormat);
+ theFactory->createTextNode(lCompressionItem, lCompression);
+
+ return true;
+ }
+
+/*******************************************************************************************
+ *******************************************************************************************/
+ bool
+ UpdateFunction::UpdateItemSequence::UpdateIterator::next(
+ zorba::Item& aRes)
+ {
+ struct archive_entry *lEntry = lookForHeader(false, &theOptions);
+
+ //NULL is EOF
+ if (!lEntry)
+ return false;
+
+ //form an ArchiveEntry with the entry
+ theEntry.setValues(lEntry);
+
+ if(archive_entry_filetype(lEntry) == AE_IFREG){
+ //read entry content
+ std::vector<unsigned char> lResult;
+
+ if (archive_entry_size_is_set(lEntry))
+ {
+ long long lSize = archive_entry_size(lEntry);
+ lResult.reserve(lSize);
+ }
+
+ std::vector<unsigned char> lBuf;
+ lBuf.resize(ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ //read entry into string
+ while (true)
+ {
+ int s = archive_read_data(
+ theArchive, &lBuf[0], ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ if (s == 0) break;
+
+ lResult.insert(lResult.end(), lBuf.begin(), lBuf.begin() + s);
+ }
+
+ aRes = theFactory->createBase64Binary(reinterpret_cast<char const*>(&lResult[0]), lResult.size(), false);
+ }
+
+ return true;
+ }
+
+ zorba::ItemSequence_t
+ UpdateFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ //Base64 Binary of the Archive
+ Item lArchive = getOneItem(aArgs, 0);
+
+ //Initialize an Update Iterator with the Archive recived from the function
+ std::auto_ptr<UpdateItemSequence> lSeq(
+ new UpdateItemSequence(lArchive, false));
+
+ std::vector<ArchiveEntry> lEntries;
+
+ //prepare list of entries to be updated into the Archive
+ {
+ Iterator_t lEntriesIter = aArgs[1]->getIterator();
+
+ zorba::Item lEntry;
+ lEntriesIter->open();
+ ExtractFunction::ExtractItemSequence::EntryNameSet& lNameSet
+ = lSeq->getNameSet();
+ while (lEntriesIter->next(lEntry))
+ {
+ lEntries.resize(lEntries.size() + 1);
+ lEntries.back().setValues(lEntry);
+ lNameSet.insert(lEntries.back().getEntryPath().str());
+ }
+ lEntriesIter->close();
+ }
+
+ //get the iterator of Files to include in the archive
+ zorba::Iterator_t lFileIter = aArgs[2]->getIterator();
+
+ //Prepare new archive, for compressing the Files form the original
+ //updated with the new Files specified
+ ArchiveCompressor lResArchive;
+ ArchiveOptions lOptions;
+
+ Item lItem;
+ Iterator_t lSeqIter = lSeq->getIterator();
+
+ //read first header and file of the archive so we can get the options before creating
+ //the new archive.
+ lSeqIter->open();
+ lSeqIter->next(lItem);
+ //set the options of the archive
+ lOptions = lSeq->getOptions();
+ //create new archive with the options read
+ lResArchive.open(lOptions);
+ if (!lItem.isNull())
+ {
+ do
+ {
+ //add and compress the files of the old archive into the new archive.
+ lResArchive.compress(lSeq->getEntry(), lItem);
+ } while (lSeqIter->next(lItem));
+ }
+ lSeqIter->close();
+
+ //add and compress the new file sspecified as a parameter for the function.
+ lResArchive.compress(lEntries, lFileIter);
+ lResArchive.close();
+
+ Item lRes = theModule->getItemFactory()->
+ createStreamableBase64Binary(
+ *lResArchive.getResultStream(),
+ &(ArchiveFunction::ArchiveCompressor::releaseStream),
+ true, // seekable
+ false // no encoded
+ );
+ return ItemSequence_t(new SingletonItemSequence(lRes));
+ }
+
+/*******************************************************************************************
+ *******************************************************************************************/
+ zorba::ItemSequence_t
+ DeleteFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ //Base64 Binary of the Archive
+ Item lArchive = getOneItem(aArgs, 0);
+
+ std::auto_ptr<DeleteItemSequence> lSeq(
+ new DeleteItemSequence(lArchive));
+
+ //set list of files to delete from the archive.
+ zorba::Item lItem;
+ Iterator_t lIter = aArgs[1]->getIterator();
+ lIter->open();
+ ExtractFunction::ExtractItemSequence::EntryNameSet& lNameSet =
+ lSeq->getNameSet();
+ while (lIter->next(lItem))
+ {
+ lNameSet.insert(lItem.getStringValue().str());
+ }
+ lIter->close();
+
+ //prepare new archive
+ ArchiveCompressor lResArchive;
+ ArchiveOptions lOptions;
+
+ Item lContent;
+ Iterator_t lSeqIter = lSeq->getIterator();
+
+ //read first header and file of the archive so we can get the options before creating
+ //the new archive.
+ lSeqIter->open();
+ lSeqIter->next(lContent);
+ //set the options of the archive
+ lOptions = lSeq->getOptions();
+ //create new archive with the options read
+ lResArchive.open(lOptions);
+ if (!lContent.isNull())
+ {
+ do
+ {
+ //add and compress the files of the old archive into the new archive.
+ lResArchive.compress(lSeq->getEntry(), lContent);
+ } while (lSeqIter->next(lContent));
+ }
+ lSeqIter->close();
+
+ lResArchive.close();
+
+ zorba::Item lRes = theModule->getItemFactory()->
+ createStreamableBase64Binary(
+ *lResArchive.getResultStream(),
+ &(ArchiveFunction::ArchiveCompressor::releaseStream),
+ true, // seekable
+ false // not encoded
+ );
+ return ItemSequence_t(new SingletonItemSequence(lRes));
+ }
+
+ bool
+ DeleteFunction::DeleteItemSequence::DeleteIterator::next(
+ zorba::Item& aRes)
+ {
+ struct archive_entry *lEntry = lookForHeader(false, &theOptions);
+
+ //NULL is EOF
+ if (!lEntry)
+ return false;
+
+ //form an ArchiveEntry with the entry
+ theEntry.setValues(lEntry);
+
+ if(archive_entry_filetype(lEntry) == AE_IFREG){
+
+ //read entry content
+ std::vector<unsigned char> lResult;
+
+ if (archive_entry_size_is_set(lEntry))
+ {
+ long long lSize = archive_entry_size(lEntry);
+ lResult.reserve(lSize);
+ }
+
+ std::vector<unsigned char> lBuf;
+ lBuf.resize(ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ //read entry into string
+ while (true)
+ {
+ int s = archive_read_data(
+ theArchive, &lBuf[0], ZORBA_ARCHIVE_MAX_READ_BUF);
+
+ if (s == 0) break;
+
+ lResult.insert(lResult.end(), lBuf.begin(), lBuf.begin() + s);
+ }
+
+ aRes = theFactory->createBase64Binary(reinterpret_cast<char const*>(&lResult[0]), lResult.size(), false);
+ }
+ // else? if the entry represents a directory what are we
+ // going to return??
+
+ return true;
+ }
+
+} /* namespace zorba */ } /* namespace archive*/
+
+std::ostream& std::operator<<(
+ std::ostream& out,
+ const zorba::archive::ArchiveFunction::ArchiveEntry& e)
+{
+ out << "name " << e.getEntryPath() << "; encoding " << e.getEncoding()
+ << "; last-modified " << e.getLastModified();
+ return out;
+}
+
+
+#ifdef WIN32
+# define DLL_EXPORT __declspec(dllexport)
+#else
+# define DLL_EXPORT __attribute__ ((visibility("default")))
+#endif
+
+extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
+ return new zorba::archive::ArchiveModule();
+}
=== added file 'src/archive_module.xq.src/archive_module.h'
--- src/archive_module.xq.src/archive_module.h 1970-01-01 00:00:00 +0000
+++ src/archive_module.xq.src/archive_module.h 2013-07-17 07:51:32 +0000
@@ -0,0 +1,806 @@
+/*
+ * Copyright 2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ORG_EXPATH_NS_ARCHIVE_H_
+#define ORG_EXPATH_NS_ARCHIVE_H_
+
+#include <map>
+#include <set>
+
+#include <zorba/zorba.h>
+#include <zorba/item_factory.h>
+#include <zorba/external_module.h>
+#include <zorba/function.h>
+#include <vector>
+
+#define ZORBA_ARCHIVE_MAX_READ_BUF 2048
+
+#define ZORBA_ARCHIVE_COMPRESSION_DEFLATE 50
+#define ZORBA_ARCHIVE_COMPRESSION_STORE 51
+
+
+namespace zorba { namespace archive {
+
+/*******************************************************************************
+ ******************************************************************************/
+ class ArchiveModule : public ExternalModule {
+ protected:
+ class ltstr
+ {
+ public:
+ bool operator()(const String& s1, const String& s2) const
+ {
+ return s1.compare(s2) < 0;
+ }
+ };
+
+ typedef std::map<String, ExternalFunction*, ltstr> FuncMap_t;
+
+ FuncMap_t theFunctions;
+
+ public:
+
+ virtual ~ArchiveModule();
+
+ virtual zorba::String
+ getURI() const { return getModuleURI(); }
+
+ virtual zorba::ExternalFunction*
+ getExternalFunction(const String& localName);
+
+ virtual void destroy();
+
+ static ItemFactory*
+ getItemFactory()
+ {
+ return Zorba::getInstance(0)->getItemFactory();
+ }
+
+ static zorba::String
+ getModuleURI() { return "http://www.zorba-xquery.com/modules/archive"; }
+
+ static zorba::Item
+ createDateTimeItem(time_t&);
+
+ static void
+ parseDateTimeItem(const zorba::Item& i, time_t&);
+
+ };
+
+
+/*******************************************************************************
+ ******************************************************************************/
+ class ArchiveItemSequence : public ItemSequence
+ {
+ public:
+ struct CallbackData
+ {
+ std::istream* theStream;
+ char theBuffer[ZORBA_ARCHIVE_MAX_READ_BUF];
+ bool theSeekable;
+ bool theEnd;
+ std::streampos thePos;
+
+ CallbackData()
+ : theStream(0), theSeekable(false), theEnd(false), thePos(0) {}
+ };
+
+ public:
+ class ArchiveIterator : public Iterator
+ {
+ protected:
+ zorba::Item theArchiveItem;
+
+ struct archive* theArchive;
+
+ CallbackData theData;
+
+ // needed if theArchiveItem is not streamable an needs to be decoded
+ zorba::String theDecodedData;
+
+ zorba::ItemFactory* theFactory;
+
+ public:
+ ArchiveIterator(zorba::Item& aArchive);
+
+ virtual ~ArchiveIterator() {}
+
+ void
+ open();
+
+ bool
+ next(zorba::Item& aItem) = 0;
+
+ void
+ close();
+
+ bool
+ isOpen() const { return theArchive != 0; }
+ };
+
+ protected:
+ zorba::Item theArchive;
+
+ public:
+ ArchiveItemSequence(zorba::Item& aArchive)
+ : theArchive(aArchive)
+ {}
+
+ virtual ~ArchiveItemSequence() {}
+
+ protected:
+#ifdef WIN32
+ static long
+#else
+ static ssize_t
+#endif
+ readStream(struct archive *a, void *client_data, const void **buff);
+
+ // needed for the "non-linear" zip format
+#ifdef WIN32
+ static __int64 seekStream(struct archive *a, void *data, __int64 request, int whence);
+#else
+ static off_t seekStream(struct archive *a, void *data, off_t request, int whence);
+#endif
+
+
+ };
+
+
+/*******************************************************************************
+ ******************************************************************************/
+ class ArchiveFunction : public ContextualExternalFunction
+ {
+ protected:
+ const ArchiveModule* theModule;
+
+ public:
+ class ArchiveOptions
+ {
+ protected:
+ std::string theCompression;
+ std::string theFormat;
+ bool theSkipExtraAttrs;
+
+ public:
+
+ ArchiveOptions();
+
+ const std::string&
+ getCompression() const { return theCompression; }
+
+ const std::string&
+ getFormat() const { return theFormat; }
+
+ void
+ setValues(Item&);
+
+ void
+ setValues(struct archive* aArchive);
+
+ bool
+ getSkipExtraAttrs() const { return theSkipExtraAttrs; }
+
+ protected:
+ static std::string
+ getAttributeValue(
+ const Item& aNode,
+ const String& aAttrName = "value");
+ };
+
+ class ArchiveEntry
+ {
+ public:
+ enum ArchiveEntryType { regular = 0, directory };
+
+ protected:
+ String theEntryPath;
+ String theEncoding;
+ long long theSize;
+ time_t theLastModified;
+ String theCompression;
+ ArchiveEntryType theEntryType;
+ bool theSkipExtras;
+
+ public:
+ ArchiveEntry();
+
+ const String& getEntryPath() const { return theEntryPath; }
+
+ const String& getEncoding() const { return theEncoding; }
+
+ long long getSize() const { return theSize; }
+
+ const time_t& getLastModified() const { return theLastModified; }
+
+ const String& getCompression() const { return theCompression; }
+
+ const ArchiveEntryType& getEntryType() const { return theEntryType; }
+
+ void setValues(zorba::Item& aEntry);
+
+ void setValues(struct archive_entry* aEntry);
+
+ bool skipExtras() const { return theSkipExtras; }
+ };
+
+ class ArchiveCompressor
+ {
+ protected:
+
+ struct archive *theArchive;
+ struct archive_entry *theEntry;
+ std::stringstream* theStream;
+ ArchiveOptions theOptions;
+
+ public:
+ ArchiveCompressor();
+
+ ~ArchiveCompressor();
+
+ void open(
+ const ArchiveOptions& aOptions);
+
+ void close();
+
+ void compress(
+ const std::vector<ArchiveEntry>& aEntries,
+ zorba::Iterator_t& aFiles);
+
+ void compress(
+ const ArchiveEntry& aEntry,
+ zorba::Item aFile);
+
+ std::stringstream* getResultStream();
+
+ static void
+ releaseStream(std::istream* s) { delete s; }
+
+ protected:
+ bool
+ getStream(
+ const ArchiveEntry& aEntry,
+ zorba::Item& aFile,
+ std::istream*& aResStream,
+ uint64_t& aResFileSize) const;
+
+ bool
+ getStreamForString(
+ const zorba::String& aEncoding,
+ zorba::Item& aFile,
+ std::istream*& aResStream,
+ uint64_t& aResFileSize) const;
+
+ bool
+ getStreamForBase64(
+ zorba::Item& aFile,
+ std::istream*& aResStream,
+ uint64_t& aResFileSize) const;
+
+
+ protected:
+ void
+ setOptions(const ArchiveOptions& aOptions);
+ };
+
+
+ static zorba::Item
+ getOneItem(const Arguments_t& aArgs, int aIndex);
+
+#ifdef WIN32
+ static long
+#else
+ static ssize_t
+#endif
+ writeStream(struct archive *a, void *client_data, const void *buff, size_t n);
+
+ static int
+ closeStream(struct archive *a, void *client_data);
+
+ public:
+
+ ArchiveFunction(const ArchiveModule* module);
+
+ virtual ~ArchiveFunction();
+
+ virtual String
+ getURI() const;
+
+ static void
+ throwError(const char*, const char*);
+
+ static void
+ checkForError(int aErrNo, const char* aLocalName, struct archive *a);
+
+ static std::string
+ formatName(int f);
+
+ static std::string
+ compressionName(int c);
+
+ static int
+ formatCode(const std::string&);
+
+ static int
+ compressionCode(const std::string&);
+
+ static void
+ setArchiveCompression(struct archive*, int c);
+ };
+
+/*******************************************************************************
+ ******************************************************************************/
+ class CreateFunction : public ArchiveFunction
+ {
+ public:
+ CreateFunction(const ArchiveModule* aModule)
+ : ArchiveFunction(aModule) {}
+
+ virtual ~CreateFunction(){}
+
+ virtual zorba::String
+ getLocalName() const { return "create"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+/*******************************************************************************
+ ******************************************************************************/
+ class EntriesFunction : public ArchiveFunction
+ {
+ protected:
+ class EntriesItemSequence : public ArchiveItemSequence
+ {
+ public:
+ class EntriesIterator : public ArchiveIterator
+ {
+ protected:
+ zorba::Item theUntypedQName;
+ zorba::Item theEntryName;
+ zorba::Item theUncompressedSizeName;
+ zorba::Item theLastModifiedName;
+ zorba::Item theEntryType;
+
+ public:
+ EntriesIterator(zorba::Item& aArchive);
+
+ virtual ~EntriesIterator() {}
+
+ bool
+ next(zorba::Item& aItem);
+ };
+
+ public:
+ EntriesItemSequence(zorba::Item& aArchive)
+ : ArchiveItemSequence(aArchive)
+ {}
+
+ virtual ~EntriesItemSequence() {}
+
+ zorba::Iterator_t
+ getIterator() { return new EntriesIterator(theArchive); }
+ };
+
+ public:
+ EntriesFunction(const ArchiveModule* aModule)
+ : ArchiveFunction(aModule) {}
+
+ virtual ~EntriesFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "entries"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+
+/*******************************************************************************
+ ******************************************************************************/
+ class ExtractFunction : public ArchiveFunction
+ {
+ public:
+ class ExtractItemSequence : public ArchiveItemSequence
+ {
+ public:
+
+ typedef std::set<std::string> EntryNameSet;
+ typedef EntryNameSet::const_iterator EntryNameSetIter;
+
+ class ExtractIterator : public ArchiveIterator
+ {
+ public:
+ ExtractIterator(
+ zorba::Item& aArchive,
+ EntryNameSet& aEntryNames,
+ bool aReturnAll)
+ : ArchiveIterator(aArchive),
+ theEntryNames(aEntryNames),
+ theReturnAll(aReturnAll) {}
+
+ struct archive_entry* lookForHeader(bool aMatch, ArchiveOptions* aOptions = NULL);
+
+ virtual ~ExtractIterator() {}
+
+ protected:
+ EntryNameSet& theEntryNames;
+ bool theReturnAll;
+ };
+
+ public:
+ ExtractItemSequence(
+ zorba::Item& aArchive,
+ bool aReturnAll)
+ : ArchiveItemSequence(aArchive),
+ theReturnAll(aReturnAll)
+ {}
+
+ virtual ~ExtractItemSequence() {}
+
+ EntryNameSet&
+ getNameSet() { return theEntryNames; }
+
+ protected:
+ EntryNameSet theEntryNames;
+ bool theReturnAll;
+ };
+
+ public:
+ ExtractFunction(const ArchiveModule* aModule)
+ : ArchiveFunction(aModule) {}
+
+ virtual ~ExtractFunction() {}
+ };
+
+/*******************************************************************************
+ ******************************************************************************/
+ class ExtractTextFunction : public ExtractFunction
+ {
+ protected:
+ class ExtractTextItemSequence : public ExtractItemSequence
+ {
+ public:
+ class ExtractTextIterator : public ExtractIterator
+ {
+ public:
+ ExtractTextIterator(
+ zorba::Item& aArchive,
+ ExtractItemSequence::EntryNameSet& aEntryNames,
+ bool aReturnAll,
+ zorba::String& aEncoding)
+ : ExtractIterator(aArchive, aEntryNames, aReturnAll),
+ theEncoding(aEncoding) {}
+
+ virtual ~ExtractTextIterator() {}
+
+ bool
+ next(zorba::Item& aItem);
+
+ protected:
+ zorba::String& theEncoding;
+ };
+
+ public:
+ ExtractTextItemSequence(
+ zorba::Item& aArchive,
+ bool aReturnAll,
+ zorba::String& aEncoding)
+ : ExtractItemSequence(aArchive, aReturnAll),
+ theEncoding(aEncoding)
+ {}
+
+ virtual ~ExtractTextItemSequence() {}
+
+ zorba::Iterator_t
+ getIterator()
+ {
+ return new ExtractTextIterator(
+ theArchive, theEntryNames, theReturnAll, theEncoding);
+ }
+
+ protected:
+ zorba::String theEncoding;
+ };
+
+ public:
+ ExtractTextFunction(const ArchiveModule* aModule)
+ : ExtractFunction(aModule) {}
+
+ virtual ~ExtractTextFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "extract-text"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+/*******************************************************************************
+ ******************************************************************************/
+ class ExtractBinaryFunction : public ExtractFunction
+ {
+ public:
+ class ExtractBinaryItemSequence : public ExtractItemSequence
+ {
+ public:
+ class ExtractBinaryIterator : public ExtractIterator
+ {
+ public:
+ ExtractBinaryIterator(
+ zorba::Item& aArchive,
+ ExtractItemSequence::EntryNameSet& aEntryNames,
+ bool aReturnAll)
+ : ExtractIterator(aArchive, aEntryNames, aReturnAll) {}
+
+ virtual ~ExtractBinaryIterator() {}
+
+ bool
+ next(zorba::Item& aItem);
+ };
+
+ public:
+ ExtractBinaryItemSequence(
+ zorba::Item& aArchive,
+ bool aReturnAll)
+ : ExtractItemSequence(aArchive, aReturnAll)
+ {}
+
+ virtual ~ExtractBinaryItemSequence() {}
+
+ zorba::Iterator_t
+ getIterator()
+ {
+ return new ExtractBinaryIterator(
+ theArchive, theEntryNames, theReturnAll);
+ }
+ };
+
+ public:
+ ExtractBinaryFunction(const ArchiveModule* aModule)
+ : ExtractFunction(aModule) {}
+
+ virtual ~ExtractBinaryFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "extract-binary"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+/*******************************************************************************
+ ******************************************************************************/
+ class OptionsFunction : public ArchiveFunction
+ {
+ public:
+ class OptionsItemSequence : public ArchiveItemSequence
+ {
+ public:
+ class OptionsIterator : public ArchiveIterator
+ {
+ public:
+ OptionsIterator(zorba::Item& aArchive)
+ : ArchiveIterator(aArchive) {}
+
+ virtual ~OptionsIterator() {}
+
+ void
+ open()
+ {
+ ArchiveIterator::open();
+ lExhausted = false;
+ }
+
+ bool
+ next(zorba::Item& aItem);
+
+ protected:
+ bool lExhausted;
+ };
+
+ public:
+ OptionsItemSequence(zorba::Item& aArchive)
+ : ArchiveItemSequence(aArchive)
+ {}
+
+ virtual ~OptionsItemSequence() {}
+
+ zorba::Iterator_t
+ getIterator()
+ {
+ return new OptionsIterator(theArchive);
+ }
+ };
+
+ public:
+ OptionsFunction(const ArchiveModule* aModule)
+ : ArchiveFunction(aModule) {}
+
+ virtual ~OptionsFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "options"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+
+/*******************************************************************************
+ ******************************************************************************/
+
+ class UpdateFunction : public ExtractFunction
+ {
+ class UpdateItemSequence : public ExtractItemSequence
+ {
+ public:
+ class UpdateIterator : public ExtractIterator
+ {
+ public:
+ UpdateIterator(
+ zorba::Item& aArchive,
+ EntryNameSet& aEntryNames,
+ bool aReturnAll,
+ ArchiveEntry& aEntry,
+ ArchiveOptions& aOptions)
+ : ExtractIterator(aArchive, aEntryNames, aReturnAll),
+ theEntry(aEntry),
+ theOptions(aOptions){}
+
+ virtual ~UpdateIterator() {}
+
+ bool
+ next(zorba::Item& aItem);
+
+ protected:
+ ArchiveEntry& theEntry;
+ ArchiveOptions& theOptions;
+ };
+
+ public:
+ UpdateItemSequence(
+ zorba::Item& aArchive,
+ bool aReturnAll)
+ : ExtractItemSequence(aArchive, aReturnAll)
+ {}
+
+ virtual ~UpdateItemSequence() {}
+
+ const ArchiveEntry&
+ getEntry() { return theEntry; }
+
+ ArchiveOptions&
+ getOptions() { return theOptions; }
+
+ zorba::Iterator_t
+ getIterator()
+ {
+ return new UpdateIterator(
+ theArchive, theEntryNames, theReturnAll, theEntry, theOptions);
+ }
+
+ protected:
+ ArchiveEntry theEntry;
+ ArchiveOptions theOptions;
+
+ };
+
+ public:
+ UpdateFunction(const ArchiveModule* aModule)
+ : ExtractFunction(aModule) {}
+
+ virtual ~UpdateFunction(){}
+
+ virtual zorba::String
+ getLocalName() const { return "update"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+
+/*******************************************************************************
+ ******************************************************************************/
+
+ class DeleteFunction : public ArchiveFunction{
+ protected:
+ class DeleteItemSequence : public ExtractFunction::ExtractItemSequence
+ {
+ public:
+ class DeleteIterator : public ExtractFunction::ExtractItemSequence::ExtractIterator
+ {
+ public:
+ DeleteIterator(zorba::Item& aArchive,
+ EntryNameSet& aEntryList,
+ ArchiveEntry& aEntry,
+ ArchiveOptions& aOptions)
+ : ExtractIterator(aArchive, aEntryList, false),
+ theEntry(aEntry),
+ theOptions(aOptions){}
+
+ virtual ~DeleteIterator() {}
+
+ bool
+ next(zorba::Item& aItem);
+
+ protected:
+ ArchiveEntry& theEntry;
+ ArchiveOptions& theOptions;
+ };
+
+ //public:
+ DeleteItemSequence(zorba::Item& aArchive)
+ : ExtractFunction::ExtractItemSequence(aArchive, false) {}
+
+ virtual ~DeleteItemSequence() {}
+
+ const ArchiveEntry&
+ getEntry() { return theEntry; }
+
+ ArchiveOptions&
+ getOptions() { return theOptions; }
+
+ zorba::Iterator_t
+ getIterator()
+ {
+ return new DeleteIterator(theArchive, theEntryNames, theEntry, theOptions);
+ }
+
+ protected:
+ ArchiveEntry theEntry;
+ ArchiveOptions theOptions;
+ };
+
+ public:
+ DeleteFunction(const ArchiveModule* aModule) : ArchiveFunction(aModule) {}
+
+ virtual ~DeleteFunction(){}
+
+ virtual zorba::String
+ getLocalName() const { return "delete"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+ };
+
+} /* namespace archive */ } /* namespace zorba */
+
+namespace std {
+
+ostream&
+operator<<(
+ ostream& out,
+ const zorba::archive::ArchiveFunction::ArchiveEntry& e);
+
+}
+
+#endif // _ORG_EXPATH_WWW_NS_ARCHIVE_H_
=== added file 'src/archive_module.xq.src/config.h.in'
--- src/archive_module.xq.src/config.h.in 1970-01-01 00:00:00 +0000
+++ src/archive_module.xq.src/config.h.in 2013-07-17 07:51:32 +0000
@@ -0,0 +1,6 @@
+#ifndef ZORBA_ARCHIVE_CONFIG_H
+#define ZORBA_ARCHIVE_CONFIG_H
+
+#cmakedefine ZORBA_LIBARCHIVE_HAVE_SET_COMPRESSION
+
+#endif
=== added file 'src/archive_module.xq.src/strncasecmp.h'
--- src/archive_module.xq.src/strncasecmp.h 1970-01-01 00:00:00 +0000
+++ src/archive_module.xq.src/strncasecmp.h 2013-07-17 07:51:32 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska H�olan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+
+int strcasecmp(const char *s1, const char *s2)
+{
+ const unsigned char *us1 = (const unsigned char *)s1, *us2 = (const unsigned char *)s2;
+
+ while (tolower(*us1) == tolower(*us2)) {
+ if (*us1++ == '\0')
+ return (0);
+ us2++;
+ }
+ return (tolower(*us1) - tolower(*us2));
+}
+
+int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ while(n > 0
+ && toupper((unsigned char)*s1) == toupper((unsigned char)*s2))
+ {
+ if(*s1 == '\0')
+ return 0;
+ s1++;
+ s2++;
+ n--;
+ }
+ if(n == 0)
+ return 0;
+ return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
+}
+
+#endif /* WIN32 */
=== added file 'src/archive_module.xq.src/strptime.h'
--- src/archive_module.xq.src/strptime.h 1970-01-01 00:00:00 +0000
+++ src/archive_module.xq.src/strptime.h 2013-07-17 07:51:32 +0000
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska H?gskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of KTH nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#ifdef WIN32
+
+
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include "strncasecmp.h"
+
+
+static const char *abb_weekdays[] = {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+ NULL
+};
+
+static const char *full_weekdays[] = {
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ NULL
+};
+
+static const char *abb_month[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec",
+ NULL
+};
+
+static const char *full_month[] = {
+ "January",
+ "February",
+ "Mars",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+ NULL,
+};
+
+static const char *ampm[] = {
+ "am",
+ "pm",
+ NULL
+};
+
+/*
+ * Try to match `*buf' to one of the strings in `strs'. Return the
+ * index of the matching string (or -1 if none). Also advance buf.
+ */
+
+static int
+match_string (const char **buf, const char **strs)
+{
+ int i = 0;
+
+ for (i = 0; strs[i] != NULL; ++i) {
+ int len = strlen (strs[i]);
+
+ if (strncasecmp (*buf, strs[i], len) == 0) {
+ *buf += len;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * tm_year is relative this year */
+
+const int tm_year_base = 1900;
+
+/*
+ * Return TRUE iff `year' was a leap year.
+ */
+
+static int
+is_leap_year (int year)
+{
+ return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
+}
+
+/*
+ * Return the weekday [0,6] (0 = Sunday) of the first day of `year'
+ */
+
+static int
+first_day (int year)
+{
+ int ret = 4;
+
+ for (; year > 1970; --year)
+ ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
+ return ret;
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_sun (struct tm *timeptr, int wnum)
+{
+ int fday = first_day (timeptr->tm_year + tm_year_base);
+
+ timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday;
+ if (timeptr->tm_yday < 0) {
+ timeptr->tm_wday = fday;
+ timeptr->tm_yday = 0;
+ }
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_mon (struct tm *timeptr, int wnum)
+{
+ int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
+
+ timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday;
+ if (timeptr->tm_yday < 0) {
+ timeptr->tm_wday = (fday + 1) % 7;
+ timeptr->tm_yday = 0;
+ }
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_mon4 (struct tm *timeptr, int wnum)
+{
+ int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
+ int offset = 0;
+
+ if (fday < 4)
+ offset += 7;
+
+ timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday;
+ if (timeptr->tm_yday < 0) {
+ timeptr->tm_wday = fday;
+ timeptr->tm_yday = 0;
+ }
+}
+
+/*
+ *
+ */
+
+char *
+strptime (const char *buf, const char *format, struct tm *timeptr)
+{
+ char c;
+
+ for (; (c = *format) != '\0'; ++format) {
+ char *s;
+ int ret;
+
+ if (isspace (c)) {
+ while (isspace (*buf))
+ ++buf;
+ } else if (c == '%' && format[1] != '\0') {
+ c = *++format;
+ if (c == 'E' || c == 'O')
+ c = *++format;
+ switch (c) {
+ case 'A' :
+ ret = match_string (&buf, full_weekdays);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'a' :
+ ret = match_string (&buf, abb_weekdays);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'B' :
+ ret = match_string (&buf, full_month);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_mon = ret;
+ break;
+ case 'b' :
+ case 'h' :
+ ret = match_string (&buf, abb_month);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_mon = ret;
+ break;
+ case 'C' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_year = (ret * 100) - tm_year_base;
+ buf = s;
+ break;
+ case 'c' :
+ abort ();
+ case 'D' : /* %m/%d/%y */
+ s = strptime (buf, "%m/%d/%y", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'd' :
+ case 'e' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_mday = ret;
+ buf = s;
+ break;
+ case 'H' :
+ case 'k' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_hour = ret;
+ buf = s;
+ break;
+ case 'I' :
+ case 'l' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ if (ret == 12)
+ timeptr->tm_hour = 0;
+ else
+ timeptr->tm_hour = ret;
+ buf = s;
+ break;
+ case 'j' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_yday = ret - 1;
+ buf = s;
+ break;
+ case 'm' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_mon = ret - 1;
+ buf = s;
+ break;
+ case 'M' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_min = ret;
+ buf = s;
+ break;
+ case 'n' :
+ if (*buf == '\n')
+ ++buf;
+ else
+ return NULL;
+ break;
+ case 'p' :
+ ret = match_string (&buf, ampm);
+ if (ret < 0)
+ return NULL;
+ if (timeptr->tm_hour == 0) {
+ if (ret == 1)
+ timeptr->tm_hour = 12;
+ } else
+ timeptr->tm_hour += 12;
+ break;
+ case 'r' : /* %I:%M:%S %p */
+ s = strptime (buf, "%I:%M:%S %p", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'R' : /* %H:%M */
+ s = strptime (buf, "%H:%M", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'S' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_sec = ret;
+ buf = s;
+ break;
+ case 't' :
+ if (*buf == '\t')
+ ++buf;
+ else
+ return NULL;
+ break;
+ case 'T' : /* %H:%M:%S */
+ case 'X' :
+ s = strptime (buf, "%H:%M:%S", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'u' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_wday = ret - 1;
+ buf = s;
+ break;
+ case 'w' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_wday = ret;
+ buf = s;
+ break;
+ case 'U' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ set_week_number_sun (timeptr, ret);
+ buf = s;
+ break;
+ case 'V' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ set_week_number_mon4 (timeptr, ret);
+ buf = s;
+ break;
+ case 'W' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ set_week_number_mon (timeptr, ret);
+ buf = s;
+ break;
+ case 'x' :
+ s = strptime (buf, "%Y:%m:%d", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'y' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ if (ret < 70)
+ timeptr->tm_year = 100 + ret;
+ else
+ timeptr->tm_year = ret;
+ buf = s;
+ break;
+ case 'Y' :
+ ret = strtol (buf, &s, 10);
+ if (s == buf)
+ return NULL;
+ timeptr->tm_year = ret - tm_year_base;
+ buf = s;
+ break;
+ case 'Z' :
+ abort ();
+ case '\0' :
+ --format;
+ /* FALLTHROUGH */
+ case '%' :
+ if (*buf == '%')
+ ++buf;
+ else
+ return NULL;
+ break;
+ default :
+ if (*buf == '%' || *++buf == c)
+ ++buf;
+ else
+ return NULL;
+ break;
+ }
+ } else {
+ if (*buf == c)
+ ++buf;
+ else
+ return NULL;
+ }
+ }
+ return (char *)buf;
+}
+
+#endif /* WIN32 */
+
\ No newline at end of file
=== added directory 'test'
=== renamed directory 'test' => 'test.moved'
=== added directory 'test/ExpQueryResults'
=== added file 'test/ExpQueryResults/create_01.xml.res'
--- test/ExpQueryResults/create_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/create_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+true
=== added file 'test/ExpQueryResults/create_02.xml.res'
--- test/ExpQueryResults/create_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/create_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+true
=== added file 'test/ExpQueryResults/create_03.xml.res'
--- test/ExpQueryResults/create_03.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/create_03.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+true
=== added file 'test/ExpQueryResults/delete_01.xml.res'
--- test/ExpQueryResults/delete_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/delete_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+1 abc
=== added file 'test/ExpQueryResults/delete_02.xml.res'
--- test/ExpQueryResults/delete_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/delete_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+99 98
=== added file 'test/ExpQueryResults/delete_03.xml.res'
--- test/ExpQueryResults/delete_03.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/delete_03.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+0
\ No newline at end of file
=== added file 'test/ExpQueryResults/delete_04.xml.res'
--- test/ExpQueryResults/delete_04.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/delete_04.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+1 <foo2/>
\ No newline at end of file
=== added file 'test/ExpQueryResults/dir_01.xml.res'
--- test/ExpQueryResults/dir_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/dir_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+foo.xml, bar.xml, dir1/,
\ No newline at end of file
=== added file 'test/ExpQueryResults/dir_02.xml.res'
--- test/ExpQueryResults/dir_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/dir_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+foo.xml, bar.xml,
\ No newline at end of file
=== added file 'test/ExpQueryResults/dir_03.xml.res'
--- test/ExpQueryResults/dir_03.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/dir_03.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+true
\ No newline at end of file
=== added file 'test/ExpQueryResults/dir_04.xml.res'
--- test/ExpQueryResults/dir_04.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/dir_04.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+foo.xml, bar.xml, dir1/, newdir/,
\ No newline at end of file
=== added file 'test/ExpQueryResults/entries_01.xml.res'
--- test/ExpQueryResults/entries_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/entries_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="http://www.zorba-xquery.com/modules/archive" size="0" last-modified="2012-06-15T20:11:09Z" type="directory">dir1/</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="11" last-modified="2012-06-15T20:11:09Z" type="regular">dir1/file1</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="11" last-modified="2012-06-15T20:11:03Z" type="regular">dir1/file2</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="0" last-modified="2012-06-15T20:10:51Z" type="directory">dir2/</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="6" last-modified="2012-06-15T20:10:47Z" type="regular">file1</entry>
\ No newline at end of file
=== added file 'test/ExpQueryResults/entries_02.xml.res'
--- test/ExpQueryResults/entries_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/entries_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="http://www.zorba-xquery.com/modules/archive" size="0" last-modified="2012-06-15T20:11:09Z" type="directory">dir1/</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="11" last-modified="2012-06-15T20:11:09Z" type="regular">dir1/file1</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="11" last-modified="2012-06-15T20:11:03Z" type="regular">dir1/file2</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="0" last-modified="2012-06-15T20:10:51Z" type="directory">dir2/</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="6" last-modified="2012-06-15T20:10:47Z" type="regular">file1</entry>
\ No newline at end of file
=== added file 'test/ExpQueryResults/entries_03.xml.res'
--- test/ExpQueryResults/entries_03.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/entries_03.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+<entry xmlns="http://www.zorba-xquery.com/modules/archive" size="0" last-modified="2012-06-15T20:11:09Z" type="directory">dir1/</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="11" last-modified="2012-06-15T20:11:09Z" type="regular">dir1/file1</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="11" last-modified="2012-06-15T20:11:03Z" type="regular">dir1/file2</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="0" last-modified="2012-06-15T20:10:51Z" type="directory">dir2/</entry><entry xmlns="http://www.zorba-xquery.com/modules/archive" size="6" last-modified="2012-06-15T20:10:47Z" type="regular">file1</entry>
=== added file 'test/ExpQueryResults/extract_01.xml.res'
--- test/ExpQueryResults/extract_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/extract_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,4 @@
+<text/><text>dir1/file1
+</text><text>dir1/file2
+</text><text/><text>file1
+</text>
=== added file 'test/ExpQueryResults/extract_02.xml.res'
--- test/ExpQueryResults/extract_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/extract_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<text>dir1/file1
+</text>
=== added file 'test/ExpQueryResults/extract_04.xml.res'
--- test/ExpQueryResults/extract_04.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/extract_04.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<text>ööüä
+</text>
=== added file 'test/ExpQueryResults/extract_05.xml.res'
--- test/ExpQueryResults/extract_05.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/extract_05.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="utf-8"?>
+<html xml:lang="en-us" lang="en-us" xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta charset="utf-8"/> 
+ <link rel="stylesheet" type="text/css" href="../css/commonltr.css"/>
+ <title>Archetype S </title>
+ <link type="text/css" rel="stylesheet" href="../css/epub.css"/>
+ </head>
+ <body id="d1e33">
+ <h1 class="title topictitle1">Archetype S </h1>
+ <div class="body">
+ <p class="p"> From 
+ <span class="xref broken http://linear.ups.edu/">
+ <span class="ph cmti-12">A First Course in Linear Algebra</span>
+ </span>
+ <br/>Version 2.30
+ <br/>
+ <span class="ph cmsy-10x-x-120">©</span> 2004.
+ <br/>Licensed under the 
+ <span class="xref broken http://www.gnu.org/licenses/fdl.html">GNU Free Documentation License</span>.
+ <br/>
+ <span class="xref broken http://linear.ups.edu/">
+ <span class="ph cmtt-12">http://linear.ups.edu/</span>
+ </span>
+ <br/>
+ <br/>
+ </p>
+ <p class="p">
+ <span class="ph paragraphHead">
+ <span class="ph cmbx-12">Summary</span>
+ </span> Domain is column vectors, codomain is matrices. Domain is dimension 3 and codomain is dimension 4. Not injective, not surjective. 
+ </p>
+ <p class="p">
+ <span class="ph framebox-c"/> A linear transformation: (Definition LT) 
+ </p>
+ <div class="tablenoborder">
+ <table class="table" border="1">
+ <tbody class="tbody">
+ <tr class="row">
+ <td class="entry">
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mi>T</mi>
+ <mo class="MathClass-punc">:</mo>
+ <msup>
+ <mrow>
+ <mi>ℂ</mi>
+ </mrow>
+ <mrow>
+ <mn>3</mn>
+ </mrow>
+ </msup>
+ <mo class="MathClass-rel">→</mo>
+ <msub>
+ <mrow>
+ <mi>M</mi>
+ </mrow>
+ <mrow>
+ <mn>2</mn>
+ <mn>2</mn>
+ </mrow>
+ </msub>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="1em" class="quad"/>
+ <mi>T</mi>
+ <mfenced separators="" open="(" close=")">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mi>a</mi>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mi>b</mi>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mi>c</mi>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mi>a</mi>
+ <mo class="MathClass-bin">−</mo>
+ <mi>b</mi>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ <mi>a</mi>
+ <mo class="MathClass-bin">+</mo>
+ <mn>2</mn>
+ <mi>b</mi>
+ <mo class="MathClass-bin">+</mo>
+ <mi>c</mi>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ <mi>a</mi>
+ <mo class="MathClass-bin">+</mo>
+ <mi>b</mi>
+ <mo class="MathClass-bin">+</mo>
+ <mi>c</mi>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ <mi>a</mi>
+ <mo class="MathClass-bin">−</mo>
+ <mn>6</mn>
+ <mi>b</mi>
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ <mi>c</mi>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </math>
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <p class="p">
+ <span class="ph framebox-c"/> A basis for the null space of the linear transformation: (
+ <span class="xref broken fcla-xml-2.30li52.html#d1e33__definition.KLT">Definition KLT</span>)
+ <br/>
+ </p>
+ <div class="tablenoborder">
+ <table class="table" border="1">
+ <tbody class="tbody">
+ <tr class="row">
+ <td class="entry">
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mfenced separators="" open="{" close="}">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>4</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ </math>
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <p class="p">
+ <span class="ph framebox-c"/> Injective: No. (
+ <span class="xref broken fcla-xml-2.30li52.html#d1e33__definition.ILT">Definition ILT</span>)
+ <br/>Since the kernel is nontrivial 
+ <span class="xref broken fcla-xml-2.30li52.html#d1e33__theorem.KILT">Theorem KILT</span> tells us that the linear transformation is not injective. Also, since the rank can not exceed 3, we are guaranteed to have a nullity of at least 1, just from checking dimensions of the domain and the codomain. In particular, verify that 
+ </p>
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mtable columnalign="left" class="align-star">
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <mi>T</mi>
+ <mfenced separators="" open="(" close=")">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>9</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ <mn>6</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-odd">
+ <mi>T</mi>
+ <mfenced separators="" open="(" close=")">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>9</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ <mn>6</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+ <p class="p">This demonstration that 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mi>T</mi>
+ </math>
+ </span> is not injective is constructed with the observation that 
+ </p>
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mtable columnalign="left" class="align-star">
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-bin">+</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>8</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label"/>
+ </mtr>
+ <mtr>
+ <mtd columnspan="4" class="intertext">
+ <mtext> and</mtext>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd>
+ <mspace width="2em"/>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <mi>z</mi>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>8</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-rel">∈</mo>
+ <mi mathvariant="bold-script">K</mi>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="(" close=")">
+ <mrow>
+ <mi>T</mi>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+ <p class="p">so the vector 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mi>z</mi>
+ </math>
+ </span> effectively “does nothing” in the evaluation of 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mi>T</mi>
+ </math>
+ </span>. 
+ </p>
+ <p class="p">
+ <span class="ph framebox-c"/> A basis for the range of the linear transformation: (
+ <span class="xref broken fcla-xml-2.30li53.html#d1e33__definition.RLT">Definition RLT</span>)
+ <br/>Evaluate the linear transformation on a standard basis to get a spanning set for the range (
+ <span class="xref broken fcla-xml-2.30li53.html#d1e33__theorem.SSRLT">Theorem SSRLT</span>):
+ <br/>
+ </p>
+ <div class="tablenoborder">
+ <table class="table" border="1">
+ <tbody class="tbody">
+ <tr class="row">
+ <td class="entry">
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mfenced separators="" open="{" close="}">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>6</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ </math>
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <p class="p"> If the linear transformation is injective, then the set above is guaranteed to be linearly independent (
+ <span class="xref broken fcla-xml-2.30li52.html#d1e33__theorem.ILTLI">Theorem ILTLI</span>). This spanning set may be converted to a “nice” basis, by making the vectors the rows of a matrix (perhaps after using a vector reperesentation), row-reducing, and retaining the nonzero rows (
+ <span class="xref broken fcla-xml-2.30li34.html#d1e33__theorem.BRS">Theorem BRS</span>), and perhaps un-coordinatizing. A basis for the range is: 
+ </p>
+ <div class="tablenoborder">
+ <table class="table" border="1">
+ <tbody class="tbody">
+ <tr class="row">
+ <td class="entry">
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mfenced separators="" open="{" close="}">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ </math>
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <p class="p">
+ <span class="ph framebox-c"/> Surjective: No. (
+ <span class="xref broken fcla-xml-2.30li53.html#d1e33__definition.SLT">Definition SLT</span>)
+ <br/>The dimension of the range is 2, and the codomain (
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <msub>
+ <mrow>
+ <mi>M</mi>
+ </mrow>
+ <mrow>
+ <mn>2</mn>
+ <mn>2</mn>
+ </mrow>
+ </msub>
+ </math>
+ </span>) has dimension 4. So the transformation is not surjective. Notice too that since the domain 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <msup>
+ <mrow>
+ <mi>ℂ</mi>
+ </mrow>
+ <mrow>
+ <mn>3</mn>
+ </mrow>
+ </msup>
+ </math>
+ </span> has dimension 3, it is impossible for the range to have a dimension greater than 3, and no matter what the actual definition of the function, it cannot possibly be surjective in this situation. 
+ </p>
+ <p class="p"> To be more precise, verify that 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-rel">∉</mo>
+ <mi mathvariant="bold-script">ℛ</mi>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="(" close=")">
+ <mrow>
+ <mi>T</mi>
+ </mrow>
+ </mfenced>
+ </math>
+ </span>, by setting the output of 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mi>T</mi>
+ </math>
+ </span> equal to this matrix and seeing that the resulting system of linear equations has no solution, i.e. is inconsistent. So the preimage, 
+ <span class="ph d4p_eqn_inline">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <msup>
+ <mrow>
+ <mi>T</mi>
+ </mrow>
+ <mrow>
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mrow>
+ </msup>
+ <mfenced separators="" open="(" close=")">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ </math>
+ </span>, is empty. This alone is sufficient to see that the linear transformation is not onto. 
+ </p>
+ <p class="p">
+ <span class="ph framebox-c"/> Subspace dimensions associated with the linear transformation. Examine parallels with earlier results for matrices. Verify 
+ <span class="xref broken fcla-xml-2.30li54.html#d1e30__theorem.RPNDD">Theorem RPNDD</span>. 
+ </p>
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mtable columnalign="left" class="align-star">
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <mtext> Domain dimension: </mtext>
+ <mn>3</mn>
+ </mtd>
+ <mtd class="align-even">
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-odd">
+ <mtext> Rank: </mtext>
+ <mn>2</mn>
+ </mtd>
+ <mtd class="align-even">
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-odd">
+ <mtext> Nullity: </mtext>
+ <mn>1</mn>
+ </mtd>
+ <mtd class="align-even">
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+ <p class="p">
+ <span class="ph framebox-c"/> Invertible: No.
+ <br/>Not injective (
+ <span class="xref broken fcla-xml-2.30li54.html#d1e30__theorem.ILTIS">Theorem ILTIS</span>), and the relative dimensions of the domain and codomain prohibit any possibility of being surjective. 
+ </p>
+ <p class="p">
+ <span class="ph framebox-c"/> Matrix representation (Definition MR):
+ <br/>
+ </p>
+ <p class="p d4p_eqn_block">
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <mtable columnalign="left" class="align-star">
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <mi>B</mi>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="{" close="}">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <mi>C</mi>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="{" close="}">
+ <mrow>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mo class="MathClass-punc">,</mo>
+ <mspace width="0.3em" class="thinspace"/>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd columnalign="right" class="align-odd">
+ <msubsup>
+ <mrow>
+ <mi>M</mi>
+ </mrow>
+ <mrow>
+ <mi>B</mi>
+ <mo class="MathClass-punc">,</mo>
+ <mi>C</mi>
+ </mrow>
+ <mrow>
+ <mi>T</mi>
+ </mrow>
+ </msubsup>
+ </mtd>
+ <mtd class="align-even">
+ <mo class="MathClass-rel">=</mo>
+ <mfenced separators="" open="[" close="]">
+ <mrow>
+ <mtable style="text-align:axis;" equalrows="false" columnlines="none none none none none none none none none none none" equalcolumns="false" class="array">
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>0</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>2</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mn>3</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mn>1</mn>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>6</mn>
+ </mtd>
+ <mtd class="array" columnalign="center">
+ <mo class="MathClass-bin">−</mo>
+ <mn>2</mn>
+ </mtd>
+ </mtr>
+ </mtable>
+ </mrow>
+ </mfenced>
+ <mspace width="2em"/>
+ </mtd>
+ <mtd columnalign="right" class="align-label"/>
+ <mtd class="align-label">
+ <mspace width="2em"/>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+ </div>
+ <div class="related-links">
+ <div class="familylinks">
+ <div class="parentlink">
+ <strong>Parent topic:</strong>
+ <a class="link" href="fcla-xml-2.30li72.html">Appendix A Archetypes</a>
+ </div>
+ <div class="previouslink">
+ <strong>Previous topic:</strong>
+ <a class="link" href="fcla-xml-2.30li90.html">Archetype R </a>
+ </div>
+ <div class="nextlink">
+ <strong>Next topic:</strong>
+ <a class="link" href="fcla-xml-2.30li92.html">Archetype T </a>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
=== added file 'test/ExpQueryResults/extract_06.xml.res'
--- test/ExpQueryResults/extract_06.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/extract_06.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+<text>ZGlyMS9maWxlMQo=</text>
=== added file 'test/ExpQueryResults/extract_07.xml.res'
--- test/ExpQueryResults/extract_07.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/extract_07.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<text>Ym9keSB7CiAgICBtYXJnaW46IDVlbSA1ZW0gNWVtIDVlbTsKICAgIGJhY2tncm91bmQtY29sb3I6IHJnYigyNTUsMjUzLDI0OSk7CiAgICBmb250LWZhbWlseTogYXJpYWwsIHZlcmRhbmEsIHNhbnMtc2VyaWY7CiAgICBjb2xvcjpibGFjazsKfQoKbmF2I3RvYyBvbCB7CiAgICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7Cn0KCm5hdiN0b2Mgb2wgbGkgYSB7CiAgICB0ZXh0LWRlY29yYXRpb24gOiBub25lOwogICAgY29sb3I6YmxhY2s7Cn0KCmJvZHkjdGl0bGVwYWdlIHsKICAgIHRleHQtYWxpZ24gOiBjZW50ZXI7Cn0=</text><text>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxwYWNrYWdlIHZlcnNpb249IjMuMCIgeG1sOmxhbmc9ImVuIiB1bmlxdWUtaWRlbnRpZmllcj0idWlkIiBwcmVmaXg9ImNjOiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zPSJodHRwOi8vd3d3LmlkcGYub3JnLzIwMDcvb3BmIj4NCiAgICA8bWV0YWRhdGEgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4NCiAgICAgICAgPGRjOnRpdGxlIGlkPSJ0aXRsZSI+QSBGaXJzdCBDb3Vyc2UgaW4gTGluZWFyIEFsZ2VicmE8L2RjOnRpdGxlPg0KICAgICAgICA8ZGM6aWRlbnRpZmllciBpZD0idWlkIj5jb2RlLmdvb2dsZS5jb20uZXB1Yi1zYW1wbGVzLmxpbmVhci1hbGdlYnJhPC9kYzppZGVudGlmaWVyPg0KICAgICAgICA8ZGM6bGFuZ3VhZ2U+ZW48L2RjOmxhbmd1YWdlPg0KICAgICAgICA8ZGM6Y3JlYXRvcj5Sb2JlcnQgQS4gQmVlemVyPC9kYzpjcmVhdG9yPg0KICAgICAgICA8bWV0YSBwcm9wZXJ0eT0iZGN0ZXJtczptb2RpZmllZCI+MjAxMi0wMy0wNVQxMjo0NzowMFo8L21ldGE+DQogICAgICAgIDxkYzpyaWdodHM+VGhpcyB3b3JrIGlzIHNoYXJlZCB3aXRoIHRoZSBwdWJsaWMgdXNpbmcgdGhlIEdOVSBGcmVlIERvY3VtZW50YXRpb24gTGljZW5zZSwgVmVyc2lvbiAxLjIuPC9kYzpyaWdodHM+DQogICAgICAgIDxkYzpyaWdodHM+wqkgMjAwNCBieSBSb2JlcnQgQS4gQmVlemVyLjwvZGM6cmlnaHRzPg0KICAgICAgICA8bGluayByZWw9ImNjOmxpY2Vuc2UiIGhyZWY9Imh0dHA6Ly93d3cuZ251Lm9yZy9jb3B5bGVmdC9mZGwuaHRtbCIvPg0KICAgICAgICA8bWV0YSBwcm9wZXJ0eT0iZGN0ZXJtczpzb3VyY2UiPmh0dHA6Ly9saW5lYXIudXBzLmVkdTwvbWV0YT4NCiAgICA8L21ldGFkYXRhPg0KICAgIDxtYW5pZmVzdD4NCiAgICAgICAgPGl0ZW0gaWQ9ImNzczAiIGhyZWY9ImNzcy9lcHViLmNzcyIgbWVkaWEtdHlwZT0idGV4dC9jc3MiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImNzczciIGhyZWY9ImNzcy9jb21tb25sdHIuY3NzIiBtZWRpYS10eXBlPSJ0ZXh0L2NzcyIvPg0KICAgICAgICA8IS0tIDxpdGVtIGlkPSJjc3MxIiBocmVmPSJjc3MvY2hlY2svdHJlZS5jc3MiIG1lZGlhLXR5cGU9InRleHQvY3NzIi8+IDxpdGVtIGlkPSJjc3MyIiBocmVmPSJjc3MvZGVmYXVsdC90cmVlLmNzcyIgbWVkaWEtdHlwZT0idGV4dC9jc3MiLz4gPGl0ZW0gaWQ9ImNzczMiIGhyZWY9ImNzcy9mb2xkZXJzL3RyZWUuY3NzIiBtZWRpYS10eXBlPSJ0ZXh0L2NzcyIvPiA8aXRlbSBpZD0iY3NzNCIgaHJlZj0iY3NzL2xvY2FsL3RyZWUuY3NzIiBtZWRpYS10eXBlPSJ0ZXh0L2NzcyIvPiA8aXRlbSBpZD0iY3NzNSIgaHJlZj0iY3NzL21lbnUvdHJlZS5jc3MiIG1lZGlhLXR5cGU9InRleHQvY3NzIi8+IDxpdGVtIGlkPSJjc3M2IiBocmVmPSJjc3MvY29kZS5jc3MiIG1lZGlhLXR5cGU9InRleHQvY3NzIi8+IDxpdGVtIGlkPSJjc3M4IiBocmVmPSJjc3MvY29tbW9ucnRsLmNzcyIgbWVkaWEtdHlwZT0idGV4dC9jc3MiLz4gPGl0ZW0gaWQ9ImNzczkiIGhyZWY9ImNzcy9yZXNldC1odG1sNS5jc3MiIG1lZGlhLXR5cGU9InRleHQvY3NzIi8+IDxpdGVtIGlkPSJjc3MxMCIgaHJlZj0iY3NzL3Jvb3QtcGFnZS5jc3MiIG1lZGlhLXR5cGU9InRleHQvY3NzIi8+IDxpdGVtIGlkPSJjc3MxMSIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIG1lZGlhLXR5cGU9InRleHQvY3NzIi8+IDxpdGVtIGlkPSJnaWYwIiBocmVmPSJpbWcvY2hlY2svY2hlY2swLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYxIiBocmVmPSJpbWcvY2hlY2svY2hlY2sxLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYyIiBocmVmPSJpbWcvY2hlY2svY2hlY2syLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYzIiBocmVmPSJpbWcvY2hlY2svbG0uZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjQiIGhyZWY9ImltZy9jaGVjay9sbWguZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjUiIGhyZWY9ImltZy9jaGVjay9sbi5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmNiIgaHJlZj0iaW1nL2NoZWNrL2xvYWRpbmcuZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjciIGhyZWY9ImltZy9jaGVjay9scC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmOCIgaHJlZj0iaW1nL2NoZWNrL2xwaC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmOSIgaHJlZj0iaW1nL2NoZWNrL3RtLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYxMCIgaHJlZj0iaW1nL2NoZWNrL3RtaC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMTEiIGhyZWY9ImltZy9jaGVjay90bi5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMTIiIGhyZWY9ImltZy9jaGVjay90cC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMTMiIGhyZWY9ImltZy9jaGVjay90cGguZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjE0IiBocmVmPSJpbWcvY2hlY2svdmxpbmUuZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjE1IiBocmVmPSJpbWcvZGVmYXVsdC9sbS5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMTYiIGhyZWY9ImltZy9kZWZhdWx0L2xtaC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMTciIGhyZWY9ImltZy9kZWZhdWx0L2xuLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYxOCIgaHJlZj0iaW1nL2RlZmF1bHQvbG9hZGluZy5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMTkiIGhyZWY9ImltZy9kZWZhdWx0L2xwLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYyMCIgaHJlZj0iaW1nL2RlZmF1bHQvbHBoLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYyMSIgaHJlZj0iaW1nL2RlZmF1bHQvdG0uZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjIyIiBocmVmPSJpbWcvZGVmYXVsdC90bWguZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjIzIiBocmVmPSJpbWcvZGVmYXVsdC90bi5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMjQiIGhyZWY9ImltZy9kZWZhdWx0L3RwLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYyNSIgaHJlZj0iaW1nL2RlZmF1bHQvdHBoLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYyNiIgaHJlZj0iaW1nL2RlZmF1bHQvdmxpbmUuZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjI3IiBocmVmPSJpbWcvZm9sZGVycy9sbS5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMjgiIGhyZWY9ImltZy9mb2xkZXJzL2xtaC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMjkiIGhyZWY9ImltZy9mb2xkZXJzL2xuLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYzMCIgaHJlZj0iaW1nL2ZvbGRlcnMvbG9hZGluZy5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMzEiIGhyZWY9ImltZy9mb2xkZXJzL2xwLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYzMiIgaHJlZj0iaW1nL2ZvbGRlcnMvbHBoLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYzMyIgaHJlZj0iaW1nL2ZvbGRlcnMvdG0uZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjM0IiBocmVmPSJpbWcvZm9sZGVycy90bWguZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjM1IiBocmVmPSJpbWcvZm9sZGVycy90bi5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmMzYiIGhyZWY9ImltZy9mb2xkZXJzL3RwLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYzNyIgaHJlZj0iaW1nL2ZvbGRlcnMvdHBoLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWYzOCIgaHJlZj0iaW1nL2ZvbGRlcnMvdmxpbmUuZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjM5IiBocmVmPSJpbWcvbWVudS9jb2xsYXBzZS5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmNDAiIGhyZWY9ImltZy9tZW51L2NvbGxhcHNlaC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmNDEiIGhyZWY9ImltZy9tZW51L2NvbGxhcHNlb24uZ2lmIiBtZWRpYS10eXBlPSJpbWFnZS9naWYiLz4gPGl0ZW0gaWQ9ImdpZjQyIiBocmVmPSJpbWcvbWVudS9kYXNoLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWY0MyIgaHJlZj0iaW1nL21lbnUvZXhwYW5kLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWY0NCIgaHJlZj0iaW1nL21lbnUvZXhwYW5kaC5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiA8aXRlbSBpZD0iZ2lmNDUiIGhyZWY9ImltZy9tZW51L2V4cGFuZG9uLmdpZiIgbWVkaWEtdHlwZT0iaW1hZ2UvZ2lmIi8+IDxpdGVtIGlkPSJnaWY0NiIgaHJlZj0iaW1nL21lbnUvbG9hZGluZy5naWYiIG1lZGlhLXR5cGU9ImltYWdlL2dpZiIvPiAtLT4NCiAgICAgICAgPGl0ZW0gaWQ9ImMxIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL3RpdGxlcGFnZS5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9jb3B5cmlnaHQuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzMiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMi5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkzLmh0bWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTQuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzYiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvbmF2Lmh0bWwiIHByb3BlcnRpZXM9Im5hdiIvPg0KICAgICAgICA8aXRlbSBpZD0iYzciIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNS5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjOCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzkiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpOS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMxMCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxMC5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMTEiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMTEuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMTIiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMTIuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzEzIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTEzLmh0bWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMxNCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxNC5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMTUiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMTUuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzE2IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTE2Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzE3IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTE3Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzE4IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTE4Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzE5IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTIwLmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzIwIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTIxLmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzIxIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTIyLmh0bWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMyMiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkyNS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMyMyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkyOC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMyNCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkyOS5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMjUiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMzEuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMjYiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMzIuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMjciIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMzMuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMjgiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMzQuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMjkiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMzYuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzMwIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTQzLmh0bWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMzMSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk0NS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMzMiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk0Ni5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMzMyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk0OC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImMzNCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk1MC5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMzUiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNTIuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMzYiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNTMuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMzciIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNTQuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMzgiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNTUuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjMzkiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNTguaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNDAiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNTkuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNDEiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNjAuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNDIiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNjEuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNDMiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNjIuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNDQiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNjMuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzQ1IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTY0Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzQ2IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTY1Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzQ3IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTY2Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzQ4IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTY3Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzQ5IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTY4Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzUwIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTY5Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzUxIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTcwLmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzUyIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTcxLmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzUzIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTcyLmh0bWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1NCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3My5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1NSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3NC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1NiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3NS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1NyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3Ni5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1OCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3Ny5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM1OSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3OC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2MCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk3OS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2MSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4MC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2MiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4MS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2MyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4Mi5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2NCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4My5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2NSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4NC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2NiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4NS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2NyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4Ni5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2OCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4Ny5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM2OSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4OC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3MCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk4OS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3MSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5MC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3MiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5MS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3MyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5Mi5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3NCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5My5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3NSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5NC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3NiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5NS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3NyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5Ni5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM3OCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGk5Ny5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjNzkiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpOTguaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzgwIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTEwMC5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM4MSIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxMDEuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjODIiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMTAyLmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzgzIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTEwMy5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM4NCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxMDQuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjODUiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMTA1Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzg2IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTEwNi5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM4NyIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxMDcuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjODgiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpMTA4Lmh0bWwiIHByb3BlcnRpZXM9Im1hdGhtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzg5IiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTEwOS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM5MCIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxMTAuaHRtbCIvPg0KICAgICAgICA8aXRlbSBpZD0iYzkxIiBtZWRpYS10eXBlPSJhcHBsaWNhdGlvbi94aHRtbCt4bWwiIGhyZWY9InhodG1sL2ZjbGEteG1sLTIuMzBsaTExMS5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICAgICAgPGl0ZW0gaWQ9ImM5MiIgbWVkaWEtdHlwZT0iYXBwbGljYXRpb24veGh0bWwreG1sIiBocmVmPSJ4aHRtbC9mY2xhLXhtbC0yLjMwbGkxMTIuaHRtbCIgcHJvcGVydGllcz0ibWF0aG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjOTMiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNi5odG1sIi8+DQogICAgICAgIDxpdGVtIGlkPSJjOTQiIG1lZGlhLXR5cGU9ImFwcGxpY2F0aW9uL3hodG1sK3htbCIgaHJlZj0ieGh0bWwvZmNsYS14bWwtMi4zMGxpNy5odG1sIiBwcm9wZXJ0aWVzPSJtYXRobWwiLz4NCiAgICA8L21hbmlmZXN0Pg0KICAgIDxzcGluZT4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMxIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzMiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM0Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzYiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM3Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjOCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzkiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMxMCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzExIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMTIiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMxMyIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzE0Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMTUiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMxNiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzE3Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMTgiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMxOSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzIwIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMjEiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMyMiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzIzIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMjQiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMyNSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzI2Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMjciLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMyOCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzI5Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMzAiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMzMSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzMyIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMzMiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMzNCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzM1Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMzYiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImMzNyIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzM4Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjMzkiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM0MCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzQxIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNDIiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM0MyIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzQ0Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNDUiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM0NiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzQ3Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNDgiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM0OSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzUwIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNTEiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM1MiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzUzIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNTQiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM1NSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzU2Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNTciLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM1OCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzU5Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNjAiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM2MSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzYyIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNjMiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM2NCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzY1Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNjYiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM2NyIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzY4Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNjkiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM3MCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzcxIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNzIiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM3MyIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzc0Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNzUiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM3NiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzc3Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjNzgiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM3OSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzgwIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjODEiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM4MiIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzgzIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjODQiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM4NSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzg2Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjODciLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM4OCIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzg5Ii8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjOTAiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM5MSIvPg0KICAgICAgICA8aXRlbXJlZiBpZHJlZj0iYzkyIi8+DQogICAgICAgIDxpdGVtcmVmIGlkcmVmPSJjOTMiLz4NCiAgICAgICAgPGl0ZW1yZWYgaWRyZWY9ImM5NCIvPg0KICAgIDwvc3BpbmU+DQo8L3BhY2thZ2U+DQo=</text>
\ No newline at end of file
=== added file 'test/ExpQueryResults/options_01.xml.res'
--- test/ExpQueryResults/options_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/options_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<options xmlns="http://www.zorba-xquery.com/modules/archive"><format>ZIP</format><compression>DEFLATE</compression></options><options xmlns="http://www.zorba-xquery.com/modules/archive"><format>TAR</format><compression>GZIP</compression></options>
\ No newline at end of file
=== added file 'test/ExpQueryResults/options_02.xml.res'
--- test/ExpQueryResults/options_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/options_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<options xmlns="http://www.zorba-xquery.com/modules/archive"><format>TAR</format><compression>BZIP2</compression></options>
\ No newline at end of file
=== added file 'test/ExpQueryResults/update_01.xml.res'
--- test/ExpQueryResults/update_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/update_01.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+2 <bar/>
=== added file 'test/ExpQueryResults/update_02.xml.res'
--- test/ExpQueryResults/update_02.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/update_02.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+3 <foo2/>
\ No newline at end of file
=== added file 'test/ExpQueryResults/update_03.xml.res'
--- test/ExpQueryResults/update_03.xml.res 1970-01-01 00:00:00 +0000
+++ test/ExpQueryResults/update_03.xml.res 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+<D:\zorba\code\zorba_modules\archive-module\test\Queries\update_03.xq>:10,21: user-defined error [http://www.zorba-xquery.com/modules/archive#ARCH0001]: number of entries (2) doesn't match number of content arguments (1); raised at D:\zorba\code\zorba_modules\archive-module\src\archive_module.xq.src\archive_module.cpp:686
=== added directory 'test/ExpQueryResults/zip'
=== added directory 'test/Queries'
=== added file 'test/Queries/create_01.xq'
--- test/Queries/create_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/create_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,13 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := "<bar/>"
+let $archive := a:create(
+ ("foo.xml", "bar.xml"),
+ ($foo-content, $bar-content)
+)
+return
+ string-join(
+ for $a in a:entries($archive)
+ return a:extract-text($archive, $a/text())
+ ) eq concat($foo-content, $bar-content)
=== added file 'test/Queries/create_02.xq'
--- test/Queries/create_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/create_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,11 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace b = "http://zorba.io/modules/base64";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("5Pb8")
+let $archive := a:create(
+ ("foo.xml", <a:entry encoding="ISO-8859-1">bar.xml</a:entry>),
+ ($foo-content, $bar-content)
+)
+return
+ b:decode(a:extract-binary($archive, "bar.xml"), "ISO-8859-1") eq "äöü"
=== added file 'test/Queries/create_03.spec'
--- test/Queries/create_03.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/create_03.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH0099
=== added file 'test/Queries/create_03.xq'
--- test/Queries/create_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/create_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,14 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := "<bar/>"
+let $archive := a:create(
+ (<a:entry compression="store">foo.xml</a:entry>, <a:entry compression="deflate">bar.xml</a:entry>),
+ ($foo-content, $bar-content)
+)
+return
+ string-join(
+ for $a in a:entries($archive)
+ return a:extract-text($archive, $a/text())
+ ) eq concat($foo-content, $bar-content)
+
=== added file 'test/Queries/delete_01.xq'
--- test/Queries/delete_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/delete_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,12 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace b = "http://zorba.io/modules/base64";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("YWJj")
+let $archive := a:create(
+ ("foo.xml", "bar.txt"),
+ ($foo-content, $bar-content)
+)
+let $new-archive := a:delete($archive, "foo.xml")
+return (count(a:entries($new-archive)), a:extract-text($new-archive, "bar.txt"))
+
=== added file 'test/Queries/delete_02.xq'
--- test/Queries/delete_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/delete_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,7 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import schema namespace as = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+let $a := f:read-binary(resolve-uri("linear-algebra-20120306.epub"))
+let $b := a:delete($a, "EPUB/xhtml/fcla-xml-2.30li46.html")
+return (count(a:entries($a)), count(a:entries($b)))
=== added file 'test/Queries/delete_03.xq'
--- test/Queries/delete_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/delete_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,16 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("YWJj")
+let $options :=
+<a:options>
+ <a:format>TAR</a:format>
+ <a:compression>GZIP</a:compression>
+</a:options>
+let $archive0 := a:create(
+ ("foo.xml"),
+ ($foo-content),
+ $options
+)
+let $archive1 := a:delete($archive0, "foo.xml")
+return count(a:entries($archive1))
=== added file 'test/Queries/delete_04.xq'
--- test/Queries/delete_04.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/delete_04.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,21 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("YWJj")
+let $foo2-content := "<foo2/>"
+let $options :=
+<a:options>
+ <a:format>TAR</a:format>
+ <a:compression>GZIP</a:compression>
+</a:options>
+let $archive0 := a:create(
+ ("foo.xml"),
+ ($foo-content),
+ $options
+)
+let $archive1 := a:delete($archive0, "foo.xml")
+let $archive2 := a:update($archive1, "foo2.xml", $foo2-content)
+return (
+ count(a:entries($archive2)),
+ a:extract-text($archive2, "foo2.xml")
+)
=== added file 'test/Queries/dir_01.xq'
--- test/Queries/dir_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/dir_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,10 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := "<bar/>"
+let $archive := a:create(
+ ("foo.xml", "bar.xml", <entry type="directory">dir1</entry>),
+ ($foo-content, $bar-content)
+)
+return
+ for $e in a:entries($archive) return concat($e/text(), ",")
=== added file 'test/Queries/dir_02.xq'
--- test/Queries/dir_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/dir_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,11 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := "<bar/>"
+let $archive := a:create(
+ ("foo.xml", "bar.xml", <entry type="directory">dir1</entry>),
+ ($foo-content, $bar-content)
+)
+let $archive2 := a:delete($archive, "dir1/")
+return
+ for $e in a:entries($archive2) return concat($e/text(), ",")
=== added file 'test/Queries/dir_03.xq'
--- test/Queries/dir_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/dir_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,13 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := "<bar/>"
+let $archive := a:create(
+ ("foo.xml", "bar.xml", <entry type="directory">dir1</entry>),
+ ($foo-content, $bar-content)
+)
+let $archive2 := a:delete($archive, "nonexistent.xml")
+let $entries := a:entries($archive)
+let $entries2 := a:entries($archive2)
+return $entries=$entries2
+
=== added file 'test/Queries/dir_04.xq'
--- test/Queries/dir_04.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/dir_04.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,13 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $foo-content := "<foo/>"
+let $bar-content := "<bar/>"
+let $archive := a:create(
+ ("foo.xml", "bar.xml", <entry type="directory">dir1</entry>),
+ ($foo-content, $bar-content)
+)
+let $archive2 := a:update($archive, <a:entry type="directory">newdir</a:entry>, ())
+let $entries := a:entries($archive)
+let $entries2 := a:entries($archive2)
+return for $e in $entries2 return concat($e/text(), ",")
+
=== added file 'test/Queries/entries_01.xq'
--- test/Queries/entries_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/entries_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,6 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import schema namespace as = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+for $a in a:entries(f:read-binary(resolve-uri("simple.zip")))
+return validate { $a }
=== added file 'test/Queries/entries_02.xq'
--- test/Queries/entries_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/entries_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,7 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import schema namespace as = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+for $a in a:entries(f:read-binary(resolve-uri("simple.tar.gz")))
+return validate { $a }
+
=== added file 'test/Queries/entries_03.spec'
--- test/Queries/entries_03.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/entries_03.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH9999
=== added file 'test/Queries/entries_03.xq'
--- test/Queries/entries_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/entries_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,7 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import schema namespace as = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+for $a in a:entries(f:read-binary(resolve-uri("simple.tar.bz2")))
+return validate { $a }
+
=== added file 'test/Queries/entries_04.spec'
--- test/Queries/entries_04.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/entries_04.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH9999
=== added file 'test/Queries/entries_04.xq'
--- test/Queries/entries_04.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/entries_04.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,7 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import schema namespace as = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+for $a in a:entries(f:read-binary(resolve-uri("invalid.zip")))
+return validate { $a }
+
=== added file 'test/Queries/extract_01.xq'
--- test/Queries/extract_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,6 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import schema namespace as = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+for $a in a:extract-text(f:read-binary(resolve-uri("simple.zip")))
+return <text>{ $a }</text>
=== added file 'test/Queries/extract_02.xq'
--- test/Queries/extract_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,5 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+ for $a in a:extract-text(f:read-binary(fn:resolve-uri("simple.zip")), "dir1/file1")
+ return <text>{$a}</text>
=== added file 'test/Queries/extract_03.spec'
--- test/Queries/extract_03.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_03.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH0004
=== added file 'test/Queries/extract_03.xq'
--- test/Queries/extract_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,5 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+ for $a in a:extract-text(f:read-binary(fn:resolve-uri("simple.zip")), "dir1/file1", "foo")
+ return <text>{$a}</text>
=== added file 'test/Queries/extract_04.xq'
--- test/Queries/extract_04.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_04.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,5 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+for $a in a:extract-text(f:read-binary(fn:resolve-uri("transcoding.zip")), "dir2/iso-8859-1.txt", "ISO-8859-1")
+return <text>{$a}</text>
=== added file 'test/Queries/extract_05.xq'
--- test/Queries/extract_05.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_05.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,7 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+let $f := f:read-binary(resolve-uri("linear-algebra-20120306.epub"))
+for $a in a:entries($f)
+where $a/text() eq "EPUB/xhtml/fcla-xml-2.30li91.html"
+return a:extract-text($f, $a/text())
=== added file 'test/Queries/extract_06.xq'
--- test/Queries/extract_06.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_06.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,5 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+ for $a in a:extract-binary(f:read-binary(fn:resolve-uri("simple.zip")), "dir1/file1")
+ return <text>{$a}</text>
=== added file 'test/Queries/extract_07.xq'
--- test/Queries/extract_07.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/extract_07.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,6 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+let $f := f:read-binary(fn:resolve-uri("linear-algebra-20120306.epub"))
+for $a in a:entries($f)[position() > 2 and position() < 5]
+return <text>{a:extract-binary($f, $a)}</text>
=== added file 'test/Queries/invalid.zip'
--- test/Queries/invalid.zip 1970-01-01 00:00:00 +0000
+++ test/Queries/invalid.zip 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+invalid
=== added file 'test/Queries/linear-algebra-20120306.epub'
Binary files test/Queries/linear-algebra-20120306.epub 1970-01-01 00:00:00 +0000 and test/Queries/linear-algebra-20120306.epub 2013-07-17 07:51:32 +0000 differ
=== added file 'test/Queries/options_01.xq'
--- test/Queries/options_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/options_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,8 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+let $zip := f:read-binary(fn:resolve-uri("linear-algebra-20120306.epub"))
+let $tar-gz := f:read-binary(fn:resolve-uri("simple.tar.gz"))
+return (
+ a:options($zip), a:options($tar-gz)
+)
=== added file 'test/Queries/options_02.spec'
--- test/Queries/options_02.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/options_02.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH9999
=== added file 'test/Queries/options_02.xq'
--- test/Queries/options_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/options_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,5 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace f = "http://expath.org/ns/file";
+
+let $tar-bz2 := f:read-binary(fn:resolve-uri("simple.tar.bz2"))
+return a:options($tar-bz2)
=== added file 'test/Queries/options_03.spec'
--- test/Queries/options_03.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/options_03.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH9999
=== added file 'test/Queries/options_03.xq'
--- test/Queries/options_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/options_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,5 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+
+let $fake_archive := xs:base64Binary("5Pb8")
+return
+ a:options($fake_archive)
=== added file 'test/Queries/simple.tar.bz2'
Binary files test/Queries/simple.tar.bz2 1970-01-01 00:00:00 +0000 and test/Queries/simple.tar.bz2 2013-07-17 07:51:32 +0000 differ
=== added file 'test/Queries/simple.tar.gz'
Binary files test/Queries/simple.tar.gz 1970-01-01 00:00:00 +0000 and test/Queries/simple.tar.gz 2013-07-17 07:51:32 +0000 differ
=== added file 'test/Queries/simple.zip'
Binary files test/Queries/simple.zip 1970-01-01 00:00:00 +0000 and test/Queries/simple.zip 2013-07-17 07:51:32 +0000 differ
=== added file 'test/Queries/transcoding.zip'
Binary files test/Queries/transcoding.zip 1970-01-01 00:00:00 +0000 and test/Queries/transcoding.zip 2013-07-17 07:51:32 +0000 differ
=== added file 'test/Queries/update_01.xq'
--- test/Queries/update_01.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/update_01.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,12 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace b = "http://zorba.io/modules/base64";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("YWJj")
+let $archive := a:create(
+ ("foo.xml", "bar.txt"),
+ ($foo-content, $bar-content)
+)
+let $new-archive := a:update($archive, "foo.xml", "<bar/>")
+return (count(a:entries($new-archive)), a:extract-text($new-archive, "foo.xml"))
+
=== added file 'test/Queries/update_02.xq'
--- test/Queries/update_02.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/update_02.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,12 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace b = "http://zorba.io/modules/base64";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("YWJj")
+let $archive := a:create(
+ ("foo.xml", "bar.txt"),
+ ($foo-content, $bar-content)
+)
+let $new-archive := a:update($archive, "foo2.xml", "<foo2/>")
+return (count(a:entries($new-archive)), a:extract-text($new-archive, "foo2.xml"))
+
=== added file 'test/Queries/update_03.spec'
--- test/Queries/update_03.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/update_03.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH0001
=== added file 'test/Queries/update_03.xq'
--- test/Queries/update_03.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/update_03.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,12 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace b = "http://zorba.io/modules/base64";
+
+let $foo-content := "<foo/>"
+let $bar-content := xs:base64Binary("YWJj")
+let $archive := a:create(
+ ("foo.xml", "bar.txt"),
+ ($foo-content, $bar-content)
+)
+let $new-archive := a:update($archive, ("foo2.xml", "bar2.xml"), ("<foo2/>"))
+return (count(a:entries($new-archive)), a:extract-text($new-archive, "foo2.xml"))
+
=== added file 'test/Queries/update_04.spec'
--- test/Queries/update_04.spec 1970-01-01 00:00:00 +0000
+++ test/Queries/update_04.spec 2013-07-17 07:51:32 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/archive:ARCH9999
=== added file 'test/Queries/update_04.xq'
--- test/Queries/update_04.xq 1970-01-01 00:00:00 +0000
+++ test/Queries/update_04.xq 2013-07-17 07:51:32 +0000
@@ -0,0 +1,7 @@
+import module namespace a = "http://www.zorba-xquery.com/modules/archive";
+import module namespace b = "http://zorba.io/modules/base64";
+
+let $fake_archive := xs:base64Binary("YWJj")
+let $new-archive := a:update($fake_archive, "foo2.xml", "<foo2/>")
+return (count(a:entries($new-archive)), a:extract-text($new-archive, "foo2.xml"))
+
Follow ups