summaryrefslogtreecommitdiffstats
path: root/tdeprint/cups/make_driver_db_cups.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2014-11-20 12:13:02 -0600
committerTimothy Pearson <[email protected]>2014-11-20 12:13:02 -0600
commit880fec09182a500b7e19b5b1c73189040cf3421a (patch)
tree663d83e0b7d7c16ec0defcf674290aefd3c15304 /tdeprint/cups/make_driver_db_cups.cpp
parentcfa9446f2535a288f803412a996acb5dd741e8fb (diff)
downloadtdelibs-880fec09182a500b7e19b5b1c73189040cf3421a.tar.gz
tdelibs-880fec09182a500b7e19b5b1c73189040cf3421a.zip
Greatly increase database generation speed from compressed PPDs where possible
Diffstat (limited to 'tdeprint/cups/make_driver_db_cups.cpp')
-rw-r--r--tdeprint/cups/make_driver_db_cups.cpp351
1 files changed, 351 insertions, 0 deletions
diff --git a/tdeprint/cups/make_driver_db_cups.cpp b/tdeprint/cups/make_driver_db_cups.cpp
new file mode 100644
index 000000000..021c77b95
--- /dev/null
+++ b/tdeprint/cups/make_driver_db_cups.cpp
@@ -0,0 +1,351 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2001 Michael Goffioul <[email protected]>
+ * Copyright (c) 2014 Timothy Pearson <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <zlib.h>
+
+#include <tqstringlist.h>
+#include <tqlocale.h>
+
+extern "C" {
+ #include "driverparse.h"
+}
+
+#define PROCESS_PPD_FILE_CONTENTS \
+ memset(value,0,256); \
+ c1 = strchr(line,':'); \
+ if (c1) \
+ { \
+ c2 = strchr(c1,'"'); \
+ if (c2) \
+ { \
+ c2++; \
+ c1 = strchr(c2,'"'); \
+ if (c1) strlcpy(value,c2,c1-c2+1); \
+ } \
+ else \
+ { \
+ c1++; \
+ while (*c1 && isspace(*c1)) \
+ c1++; \
+ if (!*c1) \
+ continue; \
+ c2 = line+strlen(line)-1; /* point to \n */ \
+ while (*c2 && isspace(*c2)) \
+ c2--; \
+ strlcpy(value,c1,c2-c1+2); \
+ } \
+ } \
+ count++; \
+ if (strncmp(line,"*Manufacturer:",14) == 0) fprintf(output_file,"MANUFACTURER=%s\n",value); \
+ else if (strncmp(line,"*ShortNickName:",15) == 0) fprintf(output_file,"MODEL=%s\n",value); \
+ else if (strncmp(line,"*ModelName:",11) == 0) fprintf(output_file,"MODELNAME=%s\n",value); \
+ else if (strncmp(line,"*NickName:",10) == 0) strncat(desc,value,255-strlen(desc)); \
+ else if (strncmp(line,"*pnpManufacturer:",17) == 0) fprintf(output_file,"PNPMANUFACTURER=%s\n",value); \
+ else if (strncmp(line,"*pnpModel:",10) == 0) fprintf(output_file,"PNPMODEL=%s\n",value); \
+ else if (strncmp(line,"*LanguageVersion:",17) == 0) strncat(langver,value,63-strlen(langver)); \
+ else count--; \
+ /* Either we got everything we needed, or we encountered an "OpenUI" directive \
+ * and it's reasonable to assume that there's no needed info further in the file, \
+ * just stop here */ \
+ if (count >= 7 || strncmp(line, "*OpenUI", 7) == 0) \
+ { \
+ if (strlen(langver) > 0) \
+ { \
+ strncat(desc, " [", 255-strlen(desc)); \
+ strncat(desc, langver, 255-strlen(desc)); \
+ strncat(desc, "]", 255-strlen(desc)); \
+ } \
+ if (strlen(desc) > 0) \
+ fprintf(output_file, "DESCRIPTION=%s\n", desc); \
+ break; \
+ }
+
+void initPpd(const char *dirname)
+{
+ struct stat stat_res;
+ if (stat(dirname, &stat_res) == -1) {
+ fprintf(stderr, "Can't open drivers directory : %s\n", dirname);
+ return;
+ }
+
+ if (S_ISDIR(stat_res.st_mode)) {
+ DIR *dir = opendir(dirname);
+ struct dirent *entry;
+ char buffer[4096] = {0};
+ char drFile[256];
+ int len = strlen(dirname);
+
+ if (dir == NULL)
+ {
+ fprintf(stderr, "Can't open drivers directory : %s\n", dirname);
+ return;
+ }
+ while ((entry=readdir(dir)) != NULL)
+ {
+ if (strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0)
+ {
+ continue;
+ }
+ if (len+strlen(entry->d_name)+1 < 4096)
+ {
+ struct stat st;
+
+ strcpy(buffer,dirname);
+ strcat(buffer,"/");
+ strcat(buffer,entry->d_name);
+ if (stat(buffer,&st) == 0)
+ {
+ if (S_ISDIR(st.st_mode))
+ {
+ initPpd(buffer);
+ }
+ else if (S_ISREG(st.st_mode))
+ {
+ char *c = strrchr(buffer,'.');
+ snprintf(drFile, 255, "ppd:%s", buffer);
+ if (c && strncmp(c,".ppd",4) == 0)
+ {
+ addFile(drFile, "", "");
+ }
+ else if (c && strncmp(c, ".gz", 3) == 0)
+ { /* keep also compressed driver files */
+ while (c != buffer)
+ {
+ if (*(--c) == '.') break;
+ }
+ if (*c == '.' && strncmp(c, ".ppd",4) == 0)
+ {
+ addFile(drFile, "", "");
+ }
+ }
+ }
+ }
+ }
+ }
+ closedir(dir);
+ }
+ else if (access(dirname, X_OK) != -1) {
+ char *filename;
+ int n = strlen(dirname)+strlen(" list");
+ filename = (char*)malloc(n*sizeof(char)+1);
+ memset(filename,0,n);
+ strcat(filename, dirname);
+ strcat(filename, " list");
+
+ FILE* file = popen(filename, "r");
+ if (file) {
+ char * line = NULL;
+ size_t len = 0;
+ ssize_t read;
+ while ((read = getline(&line, &len, file)) != -1) {
+ char * pos1 = strstr(line, "\"");
+ if (pos1 != NULL) {
+ char * pos2 = strstr(pos1 + 1, "\"");
+ if (pos2 != NULL) {
+ *pos2 = 0;
+ char * pos3 = strstr(pos1 + 1, ":");
+ if (pos3 != NULL) {
+ char *ppduri;
+ int n2 = strlen("compressed-ppd:")+strlen(pos3+1);
+ ppduri = (char*)malloc(n2*sizeof(char)+1);
+ memset(ppduri,0,n2);
+ strcat(ppduri, "compressed-ppd:");
+ strcat(ppduri, pos3+1);
+ addFile(ppduri, dirname, pos2+1);
+ free(ppduri);
+ ppduri = NULL;
+ }
+ }
+ }
+ }
+ if (line) {
+ free(line);
+ }
+
+ pclose(file);
+ }
+ else {
+ fprintf(stderr, "Can't execute compressed driver handler : %s\n", dirname);
+ }
+
+ free(filename);
+ filename = NULL;
+ }
+ else {
+ fprintf(stderr, "Can't open drivers directory : %s\n", dirname);
+ return;
+ }
+}
+
+int parsePpdFile(const char *filename, const char *origin, const char *metadata, FILE *output_file)
+{
+ gzFile ppd_file;
+ char line[4096], value[256], langver[64] = {0}, desc[256] = {0};
+ char *c1, *c2;
+ int count = 0;
+
+ ppd_file = gzopen(filename,"r");
+ if (ppd_file == NULL)
+ {
+ fprintf(stderr, "Can't open driver file : %s\n", filename);
+ return 0;
+ }
+ fprintf(output_file,"FILE=ppd:%s\n",filename);
+
+ while (gzgets(ppd_file,line,4095) != Z_NULL)
+ {
+ PROCESS_PPD_FILE_CONTENTS
+ }
+ fprintf(output_file,"\n");
+
+ gzclose(ppd_file);
+ return 1;
+}
+
+int parseCompressedPpdFile(const char *ppdfilename, const char *origin, const char *metadata, FILE *output_file)
+{
+ char value[256], langver[64] = {0}, desc[256] = {0};
+ char *c1, *c2;
+ int count = 0;
+
+ bool useFallbackExtractionMethod = false;
+
+ if (strlen(metadata) > 0) {
+ TQString metadataProcessed(metadata);
+ metadataProcessed = metadataProcessed.stripWhiteSpace();
+ TQStringList metadataList = TQStringList::split(" ", metadataProcessed, TRUE);
+ TQLocale ppdLanguage(metadataList[0]);
+ TQString languageVersion = TQLocale::languageToString(ppdLanguage.language());
+ metadataList = TQStringList::split("\" \"", metadataProcessed, TRUE);
+ TQString description = metadataList[1];
+
+ int pos = metadataProcessed.find("MFG:");
+ if (pos < 0) {
+ pos = metadataProcessed.find("MANUFACTURER:");
+ }
+ if (pos >= 0) {
+ TQString manufacturer;
+ TQString model;
+ TQString modelName;
+ TQString pnpManufacturer;
+ TQString pnpModel;
+ TQString driver;
+ TQStringList metadataList = TQStringList::split(";", metadataProcessed.mid(pos), TRUE);
+ for (TQStringList::Iterator it = metadataList.begin(); it != metadataList.end(); ++it) {
+ TQStringList kvPair = TQStringList::split(":", *it, TRUE);
+ if ((kvPair[0].upper() == "MFG") || (kvPair[0].upper() == "MANUFACTURER")) {
+ manufacturer = kvPair[1];
+ }
+ else if ((kvPair[0].upper() == "MDL") ||(kvPair[0].upper() == "MODEL")) {
+ modelName = kvPair[1];
+ }
+// else if (kvPair[0].upper() == "PNPMANUFACTURER") {
+// pnpManufacturer = kvPair[1];
+// }
+// else if (kvPair[0].upper() == "PNPMODEL") {
+// pnpModel = kvPair[1];
+// }
+ else if ((kvPair[0].upper() == "DRV") || (kvPair[0].upper() == "DRIVER")) {
+ driver = kvPair[1];
+ }
+ }
+
+ TQStringList driverList = TQStringList::split(",", driver, TRUE);
+ driver = driverList[0];
+ if (driver.startsWith("D")) {
+ driver = driver.mid(1);
+ }
+ model = manufacturer + " " + modelName + " " + driver;
+ description = description + " [" + languageVersion + "]";
+
+ fprintf(output_file,"FILE=compressed-ppd:%s:%s\n", origin, ppdfilename);
+
+ fprintf(output_file,"MANUFACTURER=%s\n",manufacturer.ascii());
+ fprintf(output_file,"MODELNAME=%s\n",modelName.ascii());
+ fprintf(output_file,"MODEL=%s\n",model.ascii());
+ if (pnpManufacturer.length() > 0) {
+ fprintf(output_file,"PNPMANUFACTURER=%s\n",pnpManufacturer.ascii());
+ }
+ if (pnpModel.length() > 0) {
+ fprintf(output_file,"PNPMODEL=%s\n",pnpModel.ascii());
+ }
+ if (description.length() > 0) {
+ fprintf(output_file,"DESCRIPTION=%s\n",description.ascii());
+ }
+ }
+ else {
+ useFallbackExtractionMethod = true;
+ }
+ }
+
+ if (useFallbackExtractionMethod) {
+ char *filename;
+ int n = strlen(origin)+strlen(" cat ")+strlen(ppdfilename);
+ filename = (char*)malloc(n*sizeof(char)+1);
+ memset(filename,0,n);
+ strcat(filename, origin);
+ strcat(filename, " cat ");
+ strcat(filename, ppdfilename);
+
+ FILE* file = popen(filename, "r");
+ if (file) {
+ char * line = NULL;
+ size_t len = 0;
+ ssize_t read;
+
+ fprintf(output_file,"FILE=compressed-ppd:%s:%s\n", origin, ppdfilename);
+
+ while ((read = getline(&line, &len, file)) != -1) {
+ PROCESS_PPD_FILE_CONTENTS
+ }
+ if (line) {
+ free(line);
+ }
+
+ pclose(file);
+ }
+ else {
+ fprintf(stderr, "Can't open driver file : %s\n", ppdfilename);
+ return 0;
+ }
+
+ free(filename);
+ filename = NULL;
+ }
+
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ registerHandler("ppd:", initPpd, parsePpdFile);
+ registerHandler("compressed-ppd:", initPpd, parseCompressedPpdFile);
+ initFoomatic();
+ return execute(argc, argv);
+}