Sort filenames before computing document hash

When computing the hash of all files in a document package, ensure that
we process each file in alphabetical order, to guarantee that the hash
will be the same when this process is done twice for the same document.
There is no guarantee that DFStorageList will return filenames in the
same order each time.

In practice, the current implementation of DFStorageList *does* return
them in the same order, however this is only out of luck. This is due to
the current implementation of DFHashTable, and the way that its contents
are populated when reading a zip file. However, this implementation
could change in in the future, so sorting the results is necessary if we
want to guarantee the ordering.
diff --git a/DocFormats/api/src/Operations.c b/DocFormats/api/src/Operations.c
index a9f9bb2..62b6e7b 100644
--- a/DocFormats/api/src/Operations.c
+++ b/DocFormats/api/src/Operations.c
@@ -42,7 +42,7 @@
 };
 
 /**
- * Compute a hash of the set of all XML files in the archive. When the get operation is executed,
+ * Compute a hash of the set of all files in the archive. When the get operation is executed,
  * this hash is stored in the HTML file, as a record of the document from which it was generated.
  * When the put operation is executed, the hash is compared with that of the HTML file, and an error
  * reported if a mismatch occurs.
@@ -55,7 +55,7 @@
  * If someone tries to call put with a HTML document that was not originally created from this exact
  * concrete document, the operation will fail.
  */
-static int computeXMLHash(DFStorage *storage, DFHashCode *result, DFError **error)
+static int computeDocumentHash(DFStorage *storage, DFHashCode *result, DFError **error)
 {
     int ok = 0;
     *result = 0;
@@ -65,6 +65,7 @@
     const char **filenames = DFStorageList(storage,error);
     if (filenames == NULL)
         goto end;
+    DFSortStringsCaseSensitive(filenames);
     for (int i = 0; filenames[i]; i++) {
         unsigned char *buf = NULL;
         size_t nbytes = 0;
@@ -219,7 +220,7 @@
     }
 
     DFHashCode hash = 0;
-    if (!computeXMLHash(concrete->storage,&hash,error))
+    if (!computeDocumentHash(concrete->storage,&hash,error))
         return 0;
     char hashstr[100];
     snprintf(hashstr,100,"%X",hash);
@@ -277,7 +278,7 @@
     // and can rely on the element mappings from the id attributes. This comparison is ignored
     // for test cases, which specify the special value "ignore" in the meta tag.
     DFHashCode expectedHash = 0;
-    if (!computeXMLHash(concreteDoc->storage,&expectedHash,error))
+    if (!computeDocumentHash(concreteDoc->storage,&expectedHash,error))
         return 0;;
     DFHashCode actualHash = 0;
     int hashMatches = 0;