+static char*getInfoString(Dict *infoDict, char *key)
+{
+ Object obj;
+ GString *s1, *s2;
+ int i;
+
+ if (infoDict && infoDict->lookup(key, &obj)->isString()) {
+ s1 = obj.getString();
+ if ((s1->getChar(0) & 0xff) == 0xfe &&
+ (s1->getChar(1) & 0xff) == 0xff) {
+ s2 = new GString();
+ for (i = 2; i < obj.getString()->getLength(); i += 2) {
+ if (s1->getChar(i) == '\0') {
+ s2->append(s1->getChar(i+1));
+ } else {
+ delete s2;
+ s2 = new GString("<unicode>");
+ break;
+ }
+ }
+ char*ret = strdup(s2->getCString());
+ delete s2;
+ obj.free();
+ return ret;
+ } else {
+ char*ret = strdup(s1->getCString());
+ obj.free();
+ return ret;
+ }
+ }
+ return strdup("");
+}
+
+static char*getInfoDate(Dict *infoDict, char *key)
+{
+ Object obj;
+ char *s;
+
+ if (infoDict && infoDict->lookup(key, &obj)->isString()) {
+ s = obj.getString()->getCString();
+ if (s[0] == 'D' && s[1] == ':') {
+ s += 2;
+ }
+ char*ret = strdup(s);
+ obj.free();
+ return ret;
+ }
+ return strdup("");
+}
+
+char* pdf_doc_getinfo(gfxdocument_t*doc, const char*name)
+{
+ pdf_doc_internal_t*i= (pdf_doc_internal_t*)doc->internal;
+ if(!strcmp(name, "title")) return getInfoString(i->docinfo.getDict(), "Title");
+ else if(!strcmp(name, "subject")) return getInfoString(i->docinfo.getDict(), "Subject");
+ else if(!strcmp(name, "keywords")) return getInfoString(i->docinfo.getDict(), "Keywords");
+ else if(!strcmp(name, "author")) return getInfoString(i->docinfo.getDict(), "Author");
+ else if(!strcmp(name, "creator")) return getInfoString(i->docinfo.getDict(), "Creator");
+ else if(!strcmp(name, "producer")) return getInfoString(i->docinfo.getDict(), "Producer");
+ else if(!strcmp(name, "creationdate")) return getInfoDate(i->docinfo.getDict(), "CreationDate");
+ else if(!strcmp(name, "moddate")) return getInfoDate(i->docinfo.getDict(), "ModDate");
+ else if(!strcmp(name, "linearized")) return strdup(i->doc->isLinearized() ? "yes" : "no");
+ else if(!strcmp(name, "tagged")) return strdup(i->doc->getStructTreeRoot()->isDict() ? "yes" : "no");
+ else if(!strcmp(name, "encrypted")) return strdup(i->doc->isEncrypted() ? "yes" : "no");
+ else if(!strcmp(name, "oktoprint")) return strdup(i->doc->okToPrint() ? "yes" : "no");
+ else if(!strcmp(name, "oktocopy")) return strdup(i->doc->okToCopy() ? "yes" : "no");
+ else if(!strcmp(name, "oktochange")) return strdup(i->doc->okToChange() ? "yes" : "no");
+ else if(!strcmp(name, "oktoaddnotes")) return strdup(i->doc->okToAddNotes() ? "yes" : "no");
+ else if(!strcmp(name, "version")) {
+ char buf[32];
+ sprintf(buf, "%.1f", i->doc->getPDFVersion());
+ return strdup(buf);
+ }
+ return 0;
+}
+
+
+static void storeDeviceParameter(const char*name, const char*value)