From f391fa6ce2ea6ca669e093dca888f3855417a775 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 29 Oct 2015 15:24:44 +0100 Subject: [printergui] Sanitize job names (ASCII only to be extra safe) --- src/maingui/printergui.cpp | 281 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 279 insertions(+), 2 deletions(-) diff --git a/src/maingui/printergui.cpp b/src/maingui/printergui.cpp index 2467dcc..e235007 100644 --- a/src/maingui/printergui.cpp +++ b/src/maingui/printergui.cpp @@ -12,6 +12,10 @@ static QStringList knownColorOptions = QStringList() << "ColorModel" << "XRXColo static QStringList knownDuplexOptions = QStringList() << "Duplex"; static QStringList knownPageSizeOptions = QStringList() << "PageSize"; +static int isUtf8(const char *s); +static void toLatin1(char *s); +static char* cleanCupsString(const char* in); + // ____________________________________________________________________________ PrinterGui::PrinterGui(char *argv[], QWidget *parent) : QDialog(parent), @@ -293,7 +297,7 @@ void PrinterGui::on_buttonPrint_clicked() } cupsSetUser(this->user); - char jobtitle[200]; + char jobtitle[250]; const char *docName; docName = getenv("J"); if (docName == NULL) { @@ -302,7 +306,11 @@ void PrinterGui::on_buttonPrint_clicked() if (docName == NULL) { docName = "Untitled"; } - snprintf(jobtitle, sizeof(jobtitle), "gui-%d-%s (%s)", (int)getpid(), this->user, docName); + char *cleanUser = cleanCupsString(this->user); + char *cleanTitle = cleanCupsString(docName); + snprintf(jobtitle, sizeof(jobtitle), "gui-%d-%s (%s)", (int)getpid(), cleanUser, cleanTitle); + free(cleanUser); + free(cleanTitle); // Drucken jobId = cupsPrintFile(dest->name, @@ -337,3 +345,272 @@ void PrinterGui::bgTimer_timeout() } } +/** + * Checks if the given c string is UTF-8. + * Using as bool-function: + * Return value != 0 means (potentially) UTF-8, + * that is, it can be processed by UTF-8 functions without error. + * Using for in-detail detection: + * Return value 0 = not valid UTF-8 + * Return value 1 = valid ASCII (which is a subset of UTF-8) + * Return value 2 = valid UTF-8, but not valid ASCII. + */ +static int isUtf8(const char *s) +{ + bool isAscii = true; + while (*s != '\0') { + if ((s[0] & 248) == 240 && + (s[1] & 192) == 128 && + (s[2] & 192) == 128 && + (s[3] & 192) == 128) { + s += 4; + isAscii = false; + } else if ((s[0] & 240) == 224 && + (s[1] & 192) == 128 && + (s[2] & 192) == 128) { + s += 3; + isAscii = false; + } else if ((s[0] & 224) == 192 && + (s[1] & 192) == 128) { + s += 2; + isAscii = false; + } else if ((s[0] & 128) != 0) { + // Invalid UTF-8 sequence, so no ASCII either + return 0; + } else { + s+= 1; + } + } + return isAscii ? 1 : 2; +} + +static void toLatin1(char *s) +{ + char *d = s; + while (*s != '\0') { + if ((s[0] & 248) == 240 && + (s[1] & 192) == 128 && + (s[2] & 192) == 128 && + (s[3] & 192) == 128) { + d[0] = '_'; + s += 4; + } else if ((s[0] & 240) == 224 && + (s[1] & 192) == 128 && + (s[2] & 192) == 128) { + d[0] = '_'; + s += 3; + } else if ((s[0] & 224) == 192 && + (s[1] & 192) == 128) { + int c = ((s[0] & 31) << 6) | (s[1] & 63); + if (c > 255) { + d[0] = '_'; + } else { + d[0] = (char)c; + } + s += 2; + } else if ((s[0] & 128) != 0) { + // Invalid UTF-8 sequence!? + d[0] = '_'; + s+= 1; + } else { + d[0] = s[0]; + s+= 1; + } + d += 1; + } + *d = '\0'; +} + +static char* cleanCupsString(const char* in) +{ + int enc = isUtf8(in); + char *out = strdup(in); + if (enc == 2) { + // UTF-8, turn to Latin-1 + toLatin1(out); + } + // Try to convert umlauts etc., remove non-printing chars + unsigned char *tmp = (unsigned char*)out; + while (*tmp != '\0') { + if (*tmp < 0x20 || *tmp > 0x7E) { + switch (*tmp) { + case 0x84: // „ + case 0x93: // “ + case 0x94: // ” + case 0xAB: // « + case 0xBB: // » + *tmp = '"'; + break; + case 0x91: // ‘ + case 0x92: // ’ + case 0xB4: // ´ + *tmp = '\''; + break; + case 0xB7: // · + *tmp = '*'; + break; + case 0xF7: // ÷ + *tmp = '/'; + break; + case 0x82: // ‚ + case 0xB8: // ¸ + *tmp = ','; + break; + case 0x96: // – + case 0x97: // — + case 0xAC: // ¬ + *tmp = '-'; + break; + case 0xAF: // ¯ + case 0xB0: // ° + *tmp = '^'; + break; + case 0x98: // ˜ + *tmp = '~'; + break; + case 0xB9: // ¹ + *tmp = '1'; + break; + case 0xB2: // ² + *tmp = '2'; + break; + case 0xB3: // ³ + *tmp = '3'; + break; + case 0xC0: // À + case 0xC1: // Á + case 0xC2: // Â + case 0xC3: // Ã + case 0xC4: // Ä + case 0xC5: // Å + case 0xC6: // Æ + *tmp = 'A'; + break; + case 0xAA: // ª + case 0xE0: // à + case 0xE1: // á + case 0xE2: // â + case 0xE3: // ã + case 0xE4: // ä + case 0xE5: // å + case 0xE6: // æ + *tmp = 'a'; + break; + case 0xA9: // © + case 0xC7: // Ç + *tmp = 'C'; + break; + case 0xA2: // ¢ + case 0xE7: // ç + *tmp = 'c'; + break; + case 0xD0: // Ð + *tmp = 'D'; + break; + case 0xF0: // ð + *tmp = 'd'; + break; + case 0xC8: // È + case 0xC9: // É + case 0xCA: // Ê + case 0xCB: // Ë + *tmp = 'E'; + break; + case 0xE8: // è + case 0xE9: // é + case 0xEA: // ê + case 0xEB: // ë + *tmp = 'e'; + break; + case 0x83: // ƒ + *tmp = 'f'; + break; + case 0xCC: // Ì + case 0xCD: // Í + case 0xCE: // Î + case 0xCF: // Ï + *tmp = 'I'; + break; + case 0xA1: // ¡ + case 0xEC: // ì + case 0xED: // í + case 0xEE: // î + case 0xEF: // ï + *tmp = 'i'; + break; + case 0xD1: // Ñ + *tmp = 'N'; + break; + case 0xF1: // ñ + *tmp = 'n'; + break; + case 0xD2: // Ò + case 0xD3: // Ó + case 0xD4: // Ô + case 0xD5: // Õ + case 0xD6: // Ö + case 0xD8: // Ø + *tmp = 'O'; + break; + case 0xF2: // ò + case 0xF3: // ó + case 0xF4: // ô + case 0xF5: // õ + case 0xF6: // ö + case 0xF8: // ø + *tmp ='o'; + break; + case 0xA3: // £ + case 0xA7: // § + *tmp = 'P'; + break; + case 0xAE: // ® + *tmp = 'R'; + break; + case 0x8A: // Š + *tmp = 'S'; + break; + case 0x9A: // š + case 0xDF: // ß + *tmp = 's'; + break; + case 0xDE: // Þ + *tmp = 'T'; + break; + case 0xFE: // þ + *tmp = 't'; + break; + case 0xD9: // Ù + case 0xDA: // Ú + case 0xDB: // Û + case 0xDC: // Ü + *tmp = 'U'; + break; + case 0xB5: // µ + case 0xF9: // ù + case 0xFA: // ú + case 0xFB: // û + case 0xFC: // ü + *tmp = 'u'; + break; + case 0xD7: // × + *tmp = 'x'; + break; + case 0xA5: // ¥ + case 0xDD: // Ý + *tmp = 'Y'; + break; + case 0xFD: // ý + case 0xFF: // ÿ + *tmp = 'y'; + break; + default: + *tmp = '.'; + break; + } + } + tmp++; + } + return out; +} + -- cgit v1.2.3-55-g7522