Home | History | Annotate | Download | only in parser
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
      8 
      9 #include <limits.h>
     10 
     11 #include <algorithm>
     12 #include <utility>
     13 #include <vector>
     14 
     15 #include "core/fpdfapi/cpdf_modulemgr.h"
     16 #include "core/fpdfapi/parser/cpdf_array.h"
     17 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     18 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
     19 #include "core/fxcodec/fx_codec.h"
     20 #include "core/fxcrt/fx_ext.h"
     21 #include "third_party/base/stl_util.h"
     22 
     23 namespace {
     24 
     25 const uint32_t kMaxStreamSize = 20 * 1024 * 1024;
     26 
     27 bool CheckFlateDecodeParams(int Colors, int BitsPerComponent, int Columns) {
     28   if (Colors < 0 || BitsPerComponent < 0 || Columns < 0)
     29     return false;
     30 
     31   int check = Columns;
     32   if (check > 0 && Colors > INT_MAX / check)
     33     return false;
     34 
     35   check *= Colors;
     36   if (check > 0 && BitsPerComponent > INT_MAX / check)
     37     return false;
     38 
     39   return check * BitsPerComponent <= INT_MAX - 7;
     40 }
     41 
     42 }  // namespace
     43 
     44 const uint16_t PDFDocEncoding[256] = {
     45     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
     46     0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011,
     47     0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x02d8, 0x02c7, 0x02c6,
     48     0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc, 0x0020, 0x0021, 0x0022, 0x0023,
     49     0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
     50     0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
     51     0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
     52     0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
     53     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
     54     0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
     55     0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
     56     0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
     57     0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
     58     0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
     59     0x007e, 0x0000, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192,
     60     0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
     61     0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, 0x0178,
     62     0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, 0x20ac, 0x00a1,
     63     0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa,
     64     0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3,
     65     0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc,
     66     0x00bd, 0x00be, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
     67     0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce,
     68     0x00cf, 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
     69     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0,
     70     0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
     71     0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
     72     0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
     73     0x00fc, 0x00fd, 0x00fe, 0x00ff};
     74 
     75 uint32_t A85Decode(const uint8_t* src_buf,
     76                    uint32_t src_size,
     77                    uint8_t*& dest_buf,
     78                    uint32_t& dest_size) {
     79   dest_size = 0;
     80   dest_buf = nullptr;
     81   if (src_size == 0)
     82     return 0;
     83 
     84   // Count legal characters and zeros.
     85   uint32_t zcount = 0;
     86   uint32_t pos = 0;
     87   while (pos < src_size) {
     88     uint8_t ch = src_buf[pos];
     89     if (ch == 'z') {
     90       zcount++;
     91     } else if ((ch < '!' || ch > 'u') && !PDFCharIsLineEnding(ch) &&
     92                ch != ' ' && ch != '\t') {
     93       break;
     94     }
     95     pos++;
     96   }
     97   // No content to decode.
     98   if (pos == 0)
     99     return 0;
    100 
    101   // Count the space needed to contain non-zero characters. The encoding ratio
    102   // of Ascii85 is 4:5.
    103   uint32_t space_for_non_zeroes = (pos - zcount) / 5 * 4 + 4;
    104   if (zcount > (UINT_MAX - space_for_non_zeroes) / 4) {
    105     return (uint32_t)-1;
    106   }
    107   dest_buf = FX_Alloc(uint8_t, zcount * 4 + space_for_non_zeroes);
    108   size_t state = 0;
    109   uint32_t res = 0;
    110   pos = dest_size = 0;
    111   while (pos < src_size) {
    112     uint8_t ch = src_buf[pos++];
    113     if (PDFCharIsLineEnding(ch) || ch == ' ' || ch == '\t')
    114       continue;
    115 
    116     if (ch == 'z') {
    117       FXSYS_memset(dest_buf + dest_size, 0, 4);
    118       state = 0;
    119       res = 0;
    120       dest_size += 4;
    121     } else if (ch >= '!' && ch <= 'u') {
    122       res = res * 85 + ch - 33;
    123       state++;
    124       if (state == 5) {
    125         for (size_t i = 0; i < 4; i++) {
    126           dest_buf[dest_size++] = (uint8_t)(res >> (3 - i) * 8);
    127         }
    128         state = 0;
    129         res = 0;
    130       }
    131     } else {
    132       // The end or illegal character.
    133       break;
    134     }
    135   }
    136   // Handle partial group.
    137   if (state) {
    138     for (size_t i = state; i < 5; i++)
    139       res = res * 85 + 84;
    140     for (size_t i = 0; i < state - 1; i++)
    141       dest_buf[dest_size++] = (uint8_t)(res >> (3 - i) * 8);
    142   }
    143   if (pos < src_size && src_buf[pos] == '>')
    144     pos++;
    145   return pos;
    146 }
    147 
    148 uint32_t HexDecode(const uint8_t* src_buf,
    149                    uint32_t src_size,
    150                    uint8_t*& dest_buf,
    151                    uint32_t& dest_size) {
    152   dest_size = 0;
    153   if (src_size == 0) {
    154     dest_buf = nullptr;
    155     return 0;
    156   }
    157 
    158   uint32_t i = 0;
    159   // Find the end of data.
    160   while (i < src_size && src_buf[i] != '>')
    161     i++;
    162 
    163   dest_buf = FX_Alloc(uint8_t, i / 2 + 1);
    164   bool bFirst = true;
    165   for (i = 0; i < src_size; i++) {
    166     uint8_t ch = src_buf[i];
    167     if (PDFCharIsLineEnding(ch) || ch == ' ' || ch == '\t')
    168       continue;
    169 
    170     if (ch == '>') {
    171       ++i;
    172       break;
    173     }
    174     if (!std::isxdigit(ch))
    175       continue;
    176 
    177     int digit = FXSYS_toHexDigit(ch);
    178     if (bFirst)
    179       dest_buf[dest_size] = digit * 16;
    180     else
    181       dest_buf[dest_size++] += digit;
    182 
    183     bFirst = !bFirst;
    184   }
    185   if (!bFirst)
    186     dest_size++;
    187   return i;
    188 }
    189 
    190 uint32_t RunLengthDecode(const uint8_t* src_buf,
    191                          uint32_t src_size,
    192                          uint8_t*& dest_buf,
    193                          uint32_t& dest_size) {
    194   uint32_t i = 0;
    195   dest_size = 0;
    196   while (i < src_size) {
    197     if (src_buf[i] == 128)
    198       break;
    199 
    200     uint32_t old = dest_size;
    201     if (src_buf[i] < 128) {
    202       dest_size += src_buf[i] + 1;
    203       if (dest_size < old)
    204         return FX_INVALID_OFFSET;
    205       i += src_buf[i] + 2;
    206     } else {
    207       dest_size += 257 - src_buf[i];
    208       if (dest_size < old)
    209         return FX_INVALID_OFFSET;
    210       i += 2;
    211     }
    212   }
    213   if (dest_size >= kMaxStreamSize)
    214     return FX_INVALID_OFFSET;
    215 
    216   dest_buf = FX_Alloc(uint8_t, dest_size);
    217   i = 0;
    218   int dest_count = 0;
    219   while (i < src_size) {
    220     if (src_buf[i] == 128)
    221       break;
    222 
    223     if (src_buf[i] < 128) {
    224       uint32_t copy_len = src_buf[i] + 1;
    225       uint32_t buf_left = src_size - i - 1;
    226       if (buf_left < copy_len) {
    227         uint32_t delta = copy_len - buf_left;
    228         copy_len = buf_left;
    229         FXSYS_memset(dest_buf + dest_count + copy_len, '\0', delta);
    230       }
    231       FXSYS_memcpy(dest_buf + dest_count, src_buf + i + 1, copy_len);
    232       dest_count += src_buf[i] + 1;
    233       i += src_buf[i] + 2;
    234     } else {
    235       int fill = 0;
    236       if (i < src_size - 1) {
    237         fill = src_buf[i + 1];
    238       }
    239       FXSYS_memset(dest_buf + dest_count, fill, 257 - src_buf[i]);
    240       dest_count += 257 - src_buf[i];
    241       i += 2;
    242     }
    243   }
    244 
    245   return std::min(i + 1, src_size);
    246 }
    247 
    248 std::unique_ptr<CCodec_ScanlineDecoder> FPDFAPI_CreateFaxDecoder(
    249     const uint8_t* src_buf,
    250     uint32_t src_size,
    251     int width,
    252     int height,
    253     const CPDF_Dictionary* pParams) {
    254   int K = 0;
    255   bool EndOfLine = false;
    256   bool ByteAlign = false;
    257   bool BlackIs1 = false;
    258   int Columns = 1728;
    259   int Rows = 0;
    260   if (pParams) {
    261     K = pParams->GetIntegerFor("K");
    262     EndOfLine = !!pParams->GetIntegerFor("EndOfLine");
    263     ByteAlign = !!pParams->GetIntegerFor("EncodedByteAlign");
    264     BlackIs1 = !!pParams->GetIntegerFor("BlackIs1");
    265     Columns = pParams->GetIntegerFor("Columns", 1728);
    266     Rows = pParams->GetIntegerFor("Rows");
    267     if (Rows > USHRT_MAX) {
    268       Rows = 0;
    269     }
    270   }
    271   return CPDF_ModuleMgr::Get()->GetFaxModule()->CreateDecoder(
    272       src_buf, src_size, width, height, K, EndOfLine, ByteAlign, BlackIs1,
    273       Columns, Rows);
    274 }
    275 
    276 std::unique_ptr<CCodec_ScanlineDecoder> FPDFAPI_CreateFlateDecoder(
    277     const uint8_t* src_buf,
    278     uint32_t src_size,
    279     int width,
    280     int height,
    281     int nComps,
    282     int bpc,
    283     const CPDF_Dictionary* pParams) {
    284   int predictor = 0;
    285   int Colors = 0, BitsPerComponent = 0, Columns = 0;
    286   if (pParams) {
    287     predictor = pParams->GetIntegerFor("Predictor");
    288     Colors = pParams->GetIntegerFor("Colors", 1);
    289     BitsPerComponent = pParams->GetIntegerFor("BitsPerComponent", 8);
    290     Columns = pParams->GetIntegerFor("Columns", 1);
    291     if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns))
    292       return nullptr;
    293   }
    294   return CPDF_ModuleMgr::Get()->GetFlateModule()->CreateDecoder(
    295       src_buf, src_size, width, height, nComps, bpc, predictor, Colors,
    296       BitsPerComponent, Columns);
    297 }
    298 
    299 uint32_t FPDFAPI_FlateOrLZWDecode(bool bLZW,
    300                                   const uint8_t* src_buf,
    301                                   uint32_t src_size,
    302                                   CPDF_Dictionary* pParams,
    303                                   uint32_t estimated_size,
    304                                   uint8_t*& dest_buf,
    305                                   uint32_t& dest_size) {
    306   int predictor = 0;
    307   int Colors = 0;
    308   int BitsPerComponent = 0;
    309   int Columns = 0;
    310   bool bEarlyChange = true;
    311   if (pParams) {
    312     predictor = pParams->GetIntegerFor("Predictor");
    313     bEarlyChange = !!pParams->GetIntegerFor("EarlyChange", 1);
    314     Colors = pParams->GetIntegerFor("Colors", 1);
    315     BitsPerComponent = pParams->GetIntegerFor("BitsPerComponent", 8);
    316     Columns = pParams->GetIntegerFor("Columns", 1);
    317     if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns))
    318       return (uint32_t)-1;
    319   }
    320   return CPDF_ModuleMgr::Get()->GetFlateModule()->FlateOrLZWDecode(
    321       bLZW, src_buf, src_size, bEarlyChange, predictor, Colors,
    322       BitsPerComponent, Columns, estimated_size, dest_buf, dest_size);
    323 }
    324 
    325 bool PDF_DataDecode(const uint8_t* src_buf,
    326                     uint32_t src_size,
    327                     const CPDF_Dictionary* pDict,
    328                     uint8_t*& dest_buf,
    329                     uint32_t& dest_size,
    330                     CFX_ByteString& ImageEncoding,
    331                     CPDF_Dictionary*& pImageParms,
    332                     uint32_t last_estimated_size,
    333                     bool bImageAcc) {
    334   CPDF_Object* pDecoder = pDict ? pDict->GetDirectObjectFor("Filter") : nullptr;
    335   if (!pDecoder || (!pDecoder->IsArray() && !pDecoder->IsName()))
    336     return false;
    337 
    338   CPDF_Object* pParams =
    339       pDict ? pDict->GetDirectObjectFor("DecodeParms") : nullptr;
    340 
    341   std::vector<std::pair<CFX_ByteString, CPDF_Object*>> DecoderArray;
    342   if (CPDF_Array* pDecoders = pDecoder->AsArray()) {
    343     CPDF_Array* pParamsArray = ToArray(pParams);
    344     for (size_t i = 0; i < pDecoders->GetCount(); i++) {
    345       DecoderArray.push_back(
    346           {pDecoders->GetStringAt(i),
    347            pParamsArray ? pParamsArray->GetDictAt(i) : nullptr});
    348     }
    349   } else {
    350     DecoderArray.push_back(
    351         {pDecoder->GetString(), pParams ? pParams->GetDict() : nullptr});
    352   }
    353   uint8_t* last_buf = const_cast<uint8_t*>(src_buf);
    354   uint32_t last_size = src_size;
    355   int nSize = pdfium::CollectionSize<int>(DecoderArray);
    356   for (int i = 0; i < nSize; i++) {
    357     int estimated_size = i == nSize - 1 ? last_estimated_size : 0;
    358     CFX_ByteString decoder = DecoderArray[i].first;
    359     CPDF_Dictionary* pParam = ToDictionary(DecoderArray[i].second);
    360     uint8_t* new_buf = nullptr;
    361     uint32_t new_size = (uint32_t)-1;
    362     int offset = -1;
    363     if (decoder == "FlateDecode" || decoder == "Fl") {
    364       if (bImageAcc && i == nSize - 1) {
    365         ImageEncoding = "FlateDecode";
    366         dest_buf = (uint8_t*)last_buf;
    367         dest_size = last_size;
    368         pImageParms = pParam;
    369         return true;
    370       }
    371       offset = FPDFAPI_FlateOrLZWDecode(false, last_buf, last_size, pParam,
    372                                         estimated_size, new_buf, new_size);
    373     } else if (decoder == "LZWDecode" || decoder == "LZW") {
    374       offset = FPDFAPI_FlateOrLZWDecode(true, last_buf, last_size, pParam,
    375                                         estimated_size, new_buf, new_size);
    376     } else if (decoder == "ASCII85Decode" || decoder == "A85") {
    377       offset = A85Decode(last_buf, last_size, new_buf, new_size);
    378     } else if (decoder == "ASCIIHexDecode" || decoder == "AHx") {
    379       offset = HexDecode(last_buf, last_size, new_buf, new_size);
    380     } else if (decoder == "RunLengthDecode" || decoder == "RL") {
    381       if (bImageAcc && i == nSize - 1) {
    382         ImageEncoding = "RunLengthDecode";
    383         dest_buf = (uint8_t*)last_buf;
    384         dest_size = last_size;
    385         pImageParms = pParam;
    386         return true;
    387       }
    388       offset = RunLengthDecode(last_buf, last_size, new_buf, new_size);
    389     } else if (decoder == "Crypt") {
    390       continue;
    391     } else {
    392       // If we get here, assume it's an image decoder.
    393       if (decoder == "DCT") {
    394         decoder = "DCTDecode";
    395       } else if (decoder == "CCF") {
    396         decoder = "CCITTFaxDecode";
    397       }
    398       ImageEncoding = decoder;
    399       pImageParms = pParam;
    400       dest_buf = (uint8_t*)last_buf;
    401       dest_size = last_size;
    402       if (CPDF_Array* pDecoders = pDecoder->AsArray())
    403         pDecoders->RemoveAt(i + 1, pDecoders->GetCount() - i - 1);
    404       return true;
    405     }
    406     if (last_buf != src_buf) {
    407       FX_Free(last_buf);
    408     }
    409     if (offset == -1) {
    410       FX_Free(new_buf);
    411       return false;
    412     }
    413     last_buf = new_buf;
    414     last_size = new_size;
    415   }
    416   ImageEncoding = "";
    417   pImageParms = nullptr;
    418   dest_buf = last_buf;
    419   dest_size = last_size;
    420   return true;
    421 }
    422 
    423 CFX_WideString PDF_DecodeText(const uint8_t* src_data, uint32_t src_len) {
    424   CFX_WideString result;
    425   if (src_len >= 2 && ((src_data[0] == 0xfe && src_data[1] == 0xff) ||
    426                        (src_data[0] == 0xff && src_data[1] == 0xfe))) {
    427     bool bBE = src_data[0] == 0xfe;
    428     uint32_t max_chars = (src_len - 2) / 2;
    429     if (!max_chars) {
    430       return result;
    431     }
    432     if (src_data[0] == 0xff) {
    433       bBE = !src_data[2];
    434     }
    435     FX_WCHAR* dest_buf = result.GetBuffer(max_chars);
    436     const uint8_t* uni_str = src_data + 2;
    437     int dest_pos = 0;
    438     for (uint32_t i = 0; i < max_chars * 2; i += 2) {
    439       uint16_t unicode = bBE ? (uni_str[i] << 8 | uni_str[i + 1])
    440                              : (uni_str[i + 1] << 8 | uni_str[i]);
    441       if (unicode == 0x1b) {
    442         i += 2;
    443         while (i < max_chars * 2) {
    444           uint16_t unicode2 = bBE ? (uni_str[i] << 8 | uni_str[i + 1])
    445                                   : (uni_str[i + 1] << 8 | uni_str[i]);
    446           i += 2;
    447           if (unicode2 == 0x1b)
    448             break;
    449         }
    450       } else {
    451         dest_buf[dest_pos++] = unicode;
    452       }
    453     }
    454     result.ReleaseBuffer(dest_pos);
    455   } else {
    456     FX_WCHAR* dest_buf = result.GetBuffer(src_len);
    457     for (uint32_t i = 0; i < src_len; i++)
    458       dest_buf[i] = PDFDocEncoding[src_data[i]];
    459     result.ReleaseBuffer(src_len);
    460   }
    461   return result;
    462 }
    463 
    464 CFX_WideString PDF_DecodeText(const CFX_ByteString& bstr) {
    465   return PDF_DecodeText((const uint8_t*)bstr.c_str(), bstr.GetLength());
    466 }
    467 
    468 CFX_ByteString PDF_EncodeText(const FX_WCHAR* pString, int len) {
    469   if (len == -1) {
    470     len = FXSYS_wcslen(pString);
    471   }
    472   CFX_ByteString result;
    473   FX_CHAR* dest_buf1 = result.GetBuffer(len);
    474   int i;
    475   for (i = 0; i < len; i++) {
    476     int code;
    477     for (code = 0; code < 256; code++)
    478       if (PDFDocEncoding[code] == pString[i]) {
    479         break;
    480       }
    481     if (code == 256) {
    482       break;
    483     }
    484     dest_buf1[i] = code;
    485   }
    486   result.ReleaseBuffer(i);
    487   if (i == len) {
    488     return result;
    489   }
    490 
    491   if (len > INT_MAX / 2 - 1) {
    492     result.ReleaseBuffer(0);
    493     return result;
    494   }
    495 
    496   int encLen = len * 2 + 2;
    497 
    498   uint8_t* dest_buf2 = (uint8_t*)result.GetBuffer(encLen);
    499   dest_buf2[0] = 0xfe;
    500   dest_buf2[1] = 0xff;
    501   dest_buf2 += 2;
    502   for (int j = 0; j < len; j++) {
    503     *dest_buf2++ = pString[j] >> 8;
    504     *dest_buf2++ = (uint8_t)pString[j];
    505   }
    506   result.ReleaseBuffer(encLen);
    507   return result;
    508 }
    509 
    510 CFX_ByteString PDF_EncodeText(const CFX_WideString& str) {
    511   return PDF_EncodeText(str.c_str(), str.GetLength());
    512 }
    513 
    514 CFX_ByteString PDF_EncodeString(const CFX_ByteString& src, bool bHex) {
    515   CFX_ByteTextBuf result;
    516   int srclen = src.GetLength();
    517   if (bHex) {
    518     result.AppendChar('<');
    519     for (int i = 0; i < srclen; i++) {
    520       result.AppendChar("0123456789ABCDEF"[src[i] / 16]);
    521       result.AppendChar("0123456789ABCDEF"[src[i] % 16]);
    522     }
    523     result.AppendChar('>');
    524     return result.MakeString();
    525   }
    526   result.AppendChar('(');
    527   for (int i = 0; i < srclen; i++) {
    528     uint8_t ch = src[i];
    529     if (ch == 0x0a) {
    530       result << "\\n";
    531       continue;
    532     }
    533     if (ch == 0x0d) {
    534       result << "\\r";
    535       continue;
    536     }
    537     if (ch == ')' || ch == '\\' || ch == '(')
    538       result.AppendChar('\\');
    539     result.AppendChar(ch);
    540   }
    541   result.AppendChar(')');
    542   return result.MakeString();
    543 }
    544 
    545 bool FlateEncode(const uint8_t* src_buf,
    546                  uint32_t src_size,
    547                  uint8_t** dest_buf,
    548                  uint32_t* dest_size) {
    549   CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule();
    550   return pEncoders &&
    551          pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf,
    552                                              dest_size);
    553 }
    554 
    555 bool PngEncode(const uint8_t* src_buf,
    556                uint32_t src_size,
    557                uint8_t** dest_buf,
    558                uint32_t* dest_size) {
    559   CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule();
    560   return pEncoders &&
    561          pEncoders->GetFlateModule()->PngEncode(src_buf, src_size, dest_buf,
    562                                                 dest_size);
    563 }
    564 
    565 uint32_t FlateDecode(const uint8_t* src_buf,
    566                      uint32_t src_size,
    567                      uint8_t*& dest_buf,
    568                      uint32_t& dest_size) {
    569   CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule();
    570   if (pEncoders) {
    571     return pEncoders->GetFlateModule()->FlateOrLZWDecode(
    572         false, src_buf, src_size, false, 0, 0, 0, 0, 0, dest_buf, dest_size);
    573   }
    574   return 0;
    575 }
    576