Browse Source

First commit

Piotr Czajkowski 5 years ago
parent
commit
3c4919196b
14 changed files with 243 additions and 1 deletions
  1. 13 1
      README.md
  2. BIN
      export.png
  3. 25 0
      extractHistory.c
  4. 0 0
      extractHistory.h
  5. 29 0
      fileinfo.c
  6. 8 0
      fileinfo.h
  7. 22 0
      makefile
  8. 18 0
      stopif.h
  9. 58 0
      transform.c
  10. 7 0
      transform.h
  11. 12 0
      xmlbuff.c
  12. 9 0
      xmlbuff.h
  13. 35 0
      zip.c
  14. 7 0
      zip.h

+ 13 - 1
README.md

@@ -1,2 +1,14 @@
 # mqxliffHistory
-Extract history from mqxliff.
+
+If you're recording changes in your memoQ project it stores a lot of useful information. However to read it using memoQ client isn't most convenient. I've created a simple tool which will export history to easily readable HTML file.
+
+First you need to export bilingual of given document with following options:
+![Export bilingual](/export.png)
+
+Then run:
+
+	./extractHistory <your_mqxlz_file>
+
+
+You'll receive *document.html* with full version history.
+

BIN
export.png


+ 25 - 0
extractHistory.c

@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <string.h>
+#include "transform.h"
+#include "zip.h"
+#include "stopif.h"
+#include "extractHistory.h"
+
+void usage(const char *name) {
+	printf("%s inputFile\n", name);
+}
+
+int main(int argc, char **argv) {
+	if (argc < 2) {
+		usage(argv[0]);
+		return 1;
+	}
+
+	char *dot = strrchr(argv[1], '.');
+	Stopif(!dot, return 1, "Bad input file name!\n");
+
+	Stopif(!transformLoad(mqxliffHistory, sizeof(mqxliffHistory)), return 1, "Can't load transform!\n");
+	readZIP(argv[1], historyFile);
+	transformCleanup();	
+
+}

File diff suppressed because it is too large
+ 0 - 0
extractHistory.h


+ 29 - 0
fileinfo.c

@@ -0,0 +1,29 @@
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include "fileinfo.h"
+
+struct fileInfo* newFileInfo(const char *filePath) {
+	if (!strrchr(filePath, '.')) return NULL;
+
+	struct fileInfo *info = malloc(sizeof(struct fileInfo));
+	info->fullname = malloc(strlen(filePath)+1);
+	strcpy(info->fullname, filePath);
+	
+	info->_base = malloc(strlen(basename(info->fullname))+1);
+	strcpy(info->_base, basename(info->fullname));
+
+	char *dot = ".";
+	info->name = strtok(info->_base, dot);
+	info->ext = strtok(NULL, dot);
+	if (info->name && info->ext)
+		return info;
+	freeFileInfo(info);
+	return NULL;
+}
+
+void freeFileInfo(struct fileInfo *info) {
+	free(info->fullname);
+	free(info->_base);
+	free(info);
+}

+ 8 - 0
fileinfo.h

@@ -0,0 +1,8 @@
+struct fileInfo
+{
+	char *fullname, *name, *ext;
+	char *_base; // this is just for slicing
+};
+
+struct fileInfo* newFileInfo(const char *filePath);
+void freeFileInfo(struct fileInfo *info);

+ 22 - 0
makefile

@@ -0,0 +1,22 @@
+CFLAGS=`pkg-config --cflags --libs libxml-2.0` `xslt-config --cflags` -g -Wall -Wextra -O3 -std=c99
+LDLIBS=`pkg-config --libs libxml-2.0` `xslt-config --libs` -larchive
+objects=fileinfo.o transform.o zip.o xmlbuff.o
+mingwCFLAGS=`x86_64-w64-mingw32-pkg-config --cflags --libs libxml-2.0 libxslt` -g -Wall -Wextra -O3 -std=c99
+mingwLDLIBS=`x86_64-w64-mingw32-pkg-config --libs libxml-2.0 libxslt`  -larchive
+mingw=x86_64-w64-mingw32-gcc
+
+extractHistory: $(objects)
+
+win/extractHistory.exe:
+	$(mingw) $(mingwCFLAGS) -c fileinfo.c $(mingwLDLIBS)
+	$(mingw) $(mingwCFLAGS) -c transform.c $(mingwLDLIBS)
+	$(mingw) $(mingwCFLAGS) -c zip.c $(mingwLDLIBS)
+	$(mingw) $(mingwCFLAGS) -c xmlbuff.c $(mingwLDLIBS)
+	$(mingw) $(mingwCFLAGS) extractHistory.c $(objects) $(mingwLDLIBS) -o $@
+
+clean:
+	rm *.o
+
+win: win/extractHistory.exe
+
+default: extractHistory

+ 18 - 0
stopif.h

@@ -0,0 +1,18 @@
+// Borrowed from https://github.com/b-k/21st-Century-Examples
+#include <stdio.h>
+#include <stdlib.h> //abort
+
+/** Set this to \c 's' to stop the program on an error.
+    Otherwise, functions return a value on failure.*/
+char error_mode;
+
+/** To where should I write errors? If this is \c NULL, write to \c stderr. */
+FILE *error_log;
+
+#define Stopif(assertion, error_action, ...) {                    \
+        if (assertion){                                           \
+            fprintf(error_log ? error_log : stderr, __VA_ARGS__); \
+            fprintf(error_log ? error_log : stderr, "\n");        \
+            if (error_mode=='s') abort();                         \
+            else                 {error_action;}                  \
+        } }

+ 58 - 0
transform.c

@@ -0,0 +1,58 @@
+#define _GNU_SOURCE //asks stdio.h to include asprintf
+#include <string.h>
+#include <stdio.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include "transform.h"
+
+extern int xmlLoadExtDtdDefaultValue;
+
+xmlDocPtr stylesheetDoc;
+xsltStylesheetPtr stylesheet;
+int transformLoad(const char *stylesheetData, size_t stylesheetSize) {
+	xmlLoadExtDtdDefaultValue = 1;
+	xmlSubstituteEntitiesDefault(1);
+
+	stylesheetDoc = xmlReadMemory(stylesheetData, stylesheetSize, NULL, NULL, 0);
+	Stopif(!stylesheetDoc, return 0, "Unable to read stylesheet !\n");
+	stylesheet = xsltParseStylesheetDoc(stylesheetDoc);
+	Stopif(!stylesheet, return 0, "Unable to parse stylesheet !\n");
+	return 1;
+}
+
+int transformXML(XMLBuff *infile) {
+	xmlDocPtr doc, result;
+	doc = xmlReadMemory(infile->data, infile->size, infile->name, NULL, 0);
+	Stopif(!doc, return 0, "Unable to read %s!\n", infile->name);
+	result = xsltApplyStylesheet(stylesheet, doc, NULL);
+	Stopif(!result, return 0, "Transformation failed for %s!\n", infile->name);
+
+	char *outFile;
+	struct fileInfo *fi = newFileInfo(infile->name);
+	asprintf(&outFile, "%s.html", fi->name);
+	freeFileInfo(fi);
+
+	FILE *fp;
+	fp = fopen(outFile, "w");
+	Stopif(xsltSaveResultToFile(fp, result, stylesheet) < 0, return 0, "Nothing saved to %s!\n", outFile);
+	fclose(fp);
+	free(outFile);
+	
+	xmlFreeDoc(result);
+	xmlFreeDoc(doc);
+    return 1;
+}
+
+void transformCleanup() {
+	xsltFreeStylesheet(stylesheet);
+	xsltCleanupGlobals();
+    xmlCleanupParser();
+}

+ 7 - 0
transform.h

@@ -0,0 +1,7 @@
+#include "xmlbuff.h"
+#include "fileinfo.h"
+#include "stopif.h"
+
+int transformLoad(const char *stylesheetData, size_t stylesheetSize);
+int transformXML(XMLBuff *infile);
+void transformCleanup();

+ 12 - 0
xmlbuff.c

@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include "xmlbuff.h"
+
+XMLBuff *XMLBuffNew(void) {
+	XMLBuff *out = malloc(sizeof(XMLBuff));
+	*out = (XMLBuff){ .data=NULL };                          
+	return out;
+}
+
+void XMLBuffFree(XMLBuff *in) {
+	free(in);
+}

+ 9 - 0
xmlbuff.h

@@ -0,0 +1,9 @@
+typedef struct XMLBuff
+{
+	char *data;
+	const char *name;
+	int size;
+} XMLBuff;
+
+XMLBuff *XMLBuffNew(void);
+void XMLBuffFree(XMLBuff *in);

+ 35 - 0
zip.c

@@ -0,0 +1,35 @@
+#include "zip.h"
+#include "transform.h"
+#include "stopif.h"
+
+int processContent(struct archive *archiveIn, const char *fileMask) {
+	struct archive_entry *entryIn;
+
+	while (archive_read_next_header(archiveIn, &entryIn) == ARCHIVE_OK) {
+		const char* path = archive_entry_pathname(entryIn);
+		int64_t size = archive_entry_size(entryIn);
+		char buf[size];
+		Stopif(archive_read_data(archiveIn, buf, size) != size, return 0, "Archive entry has no size (%s)!\n", path);
+
+		if (strstr(path, fileMask) != NULL) {
+			XMLBuff *slide = XMLBuffNew();
+			*slide = (XMLBuff){.data=buf, .size=size, .name=path};
+			Stopif(!transformXML(slide), return 0, "Can't process file (%s)!\n", path);
+			XMLBuffFree(slide);
+		}
+	}
+	return 1;
+}
+
+int readZIP(char const *infile, const char *fileMask) {
+	struct archive *archiveIn;
+
+	archiveIn = archive_read_new();
+	archive_read_support_format_zip(archiveIn);
+	Stopif(archive_read_open_filename(archiveIn, infile, 10240) != ARCHIVE_OK, return 0, "Can't read file %s!\n", infile);
+
+	Stopif(!processContent(archiveIn, fileMask), return 0, "Can't process file %s!\n", infile);
+	
+	Stopif(archive_read_free(archiveIn) != ARCHIVE_OK, return 0, "Can't free %s!\n", infile);
+	return 1;
+}

+ 7 - 0
zip.h

@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <string.h>
+#include <archive.h>
+#include <archive_entry.h>
+
+int processContent(struct archive *archiveIn, const char *fileMask);
+int readZIP(char const *infile, const char *fileMask);

Some files were not shown because too many files changed in this diff