Changeset 17581 in niluje


Ignore:
Timestamp:
Jul 28, 2020, 7:54:58 PM (2 weeks ago)
Author:
NiLuJe
Message:

MobiCover:

  • Run a clang-format pass
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Configs/trunk/Kindle/Touch_Hacks/MobiCover/LibMobi/mobicover.c

    r17580 r17581  
    1818#include <getopt.h>
    1919#include <limits.h>
     20#include <stdio.h>
    2021#include <stdlib.h>
    21 #include <stdio.h>
    2222#include <unistd.h>
    2323
     
    3636
    3737// c.f., https://github.com/bfabiszewski/kindle-screensavers/commit/fe9eddbc5e4d330b12ad789663736dfaa717fc7a#comments
    38 int dump_cover(const MOBIData *m, const char *fullpath) {
    39     bool broken_cover = false;
    40     MOBIPdbRecord *record = NULL;
    41     size_t first_resource = mobi_get_first_resource_record(m);
    42     size_t uid = 0U;
    43     MOBIExthHeader *exth = mobi_get_exthrecord_by_tag(m, EXTH_COVEROFFSET);
    44     if (exth) {
    45         uint32_t offset = mobi_decode_exthvalue(exth->data, exth->size);
    46         if (offset != UINT32_MAX) {
    47             uid = first_resource + offset;
    48         } else {
    49             uid = first_resource;
    50             broken_cover = true;
    51             printf("Warning: EXTH CoverOffset is a NULL pointer, discarding it and assuming the first resource record has the cover!\n", uid);
    52         }
    53     } else {
    54         uid = first_resource;
    55         broken_cover = true;
    56         printf("Warning: could not determine cover location (CoverOffset missing from EXTH), assuming the first resource record has the cover!\n", uid);
    57     }
    58     record = mobi_get_record_by_seqnumber(m, uid);
    59 
    60     const unsigned char jpg_magic[] = "\xff\xd8\xff";
    61     const unsigned char gif_magic[] = "\x47\x49\x46\x38";
    62     const unsigned char png_magic[] = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a";
    63     const unsigned char bmp_magic[] = "\x42\x4d";
    64     char ext[4] = "raw";
    65 
    66     bool cover_found = false;
    67 
    68     for (; record != NULL; record = record->next) {
    69         if (record->size < 4) {
    70             continue;
    71         }
    72 
    73         if (memcmp(record->data, jpg_magic, 3) == 0) {
    74             snprintf(ext, sizeof(ext), "%s", "jpg");
    75             cover_found = true;
    76             break;
    77         } else if (memcmp(record->data, gif_magic, 4) == 0) {
    78             if (broken_cover) {
    79                 printf("Resource record %u did not appear to be the cover image (it's a gif). . .\n", record->uid);
    80                 continue;
    81             }
    82             snprintf(ext, sizeof(ext), "%s", "gif");
    83             cover_found = true;
    84             break;
    85         } else if (record->size >= 8 && memcmp(record->data, png_magic, 8) == 0) {
    86             if (broken_cover) {
    87                 printf("Resource record %u did not appear to be the cover image (it's a png). . .\n", record->uid);
    88                 continue;
    89             }
    90             snprintf(ext, sizeof(ext), "%s", "png");
    91             cover_found = true;
    92             break;
    93         } else if (record->size >= 6 && memcmp(record->data, bmp_magic, 2) == 0) {
    94             const size_t bmp_size = (uint32_t) record->data[2] | ((uint32_t) record->data[3] << 8) |
    95             ((uint32_t) record->data[4] << 16) | ((uint32_t) record->data[5] << 24);
    96             if (record->size == bmp_size) {
    97                 if (broken_cover) {
    98                     printf("Resource record %u did not appear to be the cover image (it's a bmp). . .\n", record->uid);
    99                     continue;
    100                 }
    101                 snprintf(ext, sizeof(ext), "%s", "bmp");
    102                 cover_found = true;
    103                 break;
    104             }
    105         } else {
    106             printf("Cover not found in record %u\n", record->uid);
    107             continue;
    108         }
    109     }
    110 
    111     if (!cover_found) {
    112         printf("Unable to find a cover!\n");
    113         return ERRCODE(EXIT_FAILURE);
    114     }
    115 
    116     char dirname[FILENAME_MAX];
    117     char basename[FILENAME_MAX];
    118     split_fullpath(fullpath, dirname, basename);
    119 
    120     char *asin = mobi_meta_get_asin(m);
    121     char *cdekey = NULL;
    122     if (asin) {
    123         cdekey = asin;
    124     } else {
    125         // Use the sha1 of the full path, like the Kindle
    126         char abspath[PATH_MAX];
    127         (void) realpath(fullpath, abspath);
    128 
    129         unsigned char hash[SHA1_DIGEST_SIZE];
    130         SHA1_CTX ctx;
    131         SHA1_Init(&ctx);
    132         SHA1_Update(&ctx, abspath, strlen(abspath));
    133         SHA1_Final(&ctx, hash);
    134 
    135         // c.f., https://git.lysator.liu.se/nettle/nettle/-/blob/master/base16-encode.c
    136         static const uint8_t hex_digits[16] = "0123456789abcdef";
    137         #define DIGIT(x) (hex_digits[(x) & 0xf])
    138         char hex_hash[SHA1_DIGEST_SIZE * 2] = { 0 };
    139         uint8_t *src = hash;
    140         char *dst = hex_hash;
    141         for (size_t i = 0; i < SHA1_DIGEST_SIZE; i++, dst += 2) {
    142             dst[0] = DIGIT(src[i] / 0x10);
    143             dst[1] = DIGIT(src[i]);
    144         }
    145 
    146         cdekey = hex_hash;
    147     }
    148     char cover_path[FILENAME_MAX];
    149     if (outdir_opt) {
    150         snprintf(cover_path, sizeof(cover_path), "%scover_raw_%s.%s", outdir, cdekey, ext);
    151     } else {
    152         snprintf(cover_path, sizeof(cover_path), "%scover_raw_%s.%s", dirname, cdekey, ext);
    153     }
    154     free(asin);
    155 
    156     printf("Saving cover to %s\n", cover_path);
    157     errno = 0;
    158     FILE *file = fopen(cover_path, "wb");
    159     if (file == NULL) {
    160         int errsv = errno;
    161         printf("Could not open file for writing: %s (%s)\n", cover_path, strerror(errsv));
    162         return ERRCODE(EXIT_FAILURE);
    163     }
    164     size_t count = fwrite(record->data, 1, record->size, file);
    165     if (count != record->size) {
    166         int errsv = errno;
    167         printf("Error writing to file: %s (%s)\n", cover_path, strerror(errsv));
    168         fclose(file);
    169         return ERRCODE(EXIT_FAILURE);
    170     }
    171     fclose(file);
    172 
    173     return EXIT_SUCCESS;
     38static int
     39    dump_cover(const MOBIData* m, const char* fullpath)
     40{
     41        bool            broken_cover   = false;
     42        MOBIPdbRecord*  record         = NULL;
     43        size_t          first_resource = mobi_get_first_resource_record(m);
     44        size_t          uid            = 0U;
     45        MOBIExthHeader* exth           = mobi_get_exthrecord_by_tag(m, EXTH_COVEROFFSET);
     46        if (exth) {
     47                uint32_t offset = mobi_decode_exthvalue(exth->data, exth->size);
     48                if (offset != UINT32_MAX) {
     49                        uid = first_resource + offset;
     50                } else {
     51                        uid          = first_resource;
     52                        broken_cover = true;
     53                        printf(
     54                            "Warning: EXTH CoverOffset is a NULL pointer, discarding it and assuming the first resource record has the cover!\n",
     55                            uid);
     56                }
     57        } else {
     58                uid          = first_resource;
     59                broken_cover = true;
     60                printf(
     61                    "Warning: could not determine cover location (CoverOffset missing from EXTH), assuming the first resource record has the cover!\n",
     62                    uid);
     63        }
     64        record = mobi_get_record_by_seqnumber(m, uid);
     65
     66        const unsigned char jpg_magic[] = "\xff\xd8\xff";
     67        const unsigned char gif_magic[] = "\x47\x49\x46\x38";
     68        const unsigned char png_magic[] = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a";
     69        const unsigned char bmp_magic[] = "\x42\x4d";
     70        char                ext[4]      = "raw";
     71
     72        bool cover_found = false;
     73
     74        for (; record != NULL; record = record->next) {
     75                if (record->size < 4) {
     76                        continue;
     77                }
     78
     79                if (memcmp(record->data, jpg_magic, 3) == 0) {
     80                        snprintf(ext, sizeof(ext), "%s", "jpg");
     81                        cover_found = true;
     82                        break;
     83                } else if (memcmp(record->data, gif_magic, 4) == 0) {
     84                        if (broken_cover) {
     85                                printf("Resource record %u did not appear to be the cover image (it's a gif). . .\n",
     86                                       record->uid);
     87                                continue;
     88                        }
     89                        snprintf(ext, sizeof(ext), "%s", "gif");
     90                        cover_found = true;
     91                        break;
     92                } else if (record->size >= 8 && memcmp(record->data, png_magic, 8) == 0) {
     93                        if (broken_cover) {
     94                                printf("Resource record %u did not appear to be the cover image (it's a png). . .\n",
     95                                       record->uid);
     96                                continue;
     97                        }
     98                        snprintf(ext, sizeof(ext), "%s", "png");
     99                        cover_found = true;
     100                        break;
     101                } else if (record->size >= 6 && memcmp(record->data, bmp_magic, 2) == 0) {
     102                        const size_t bmp_size = (uint32_t) record->data[2] | ((uint32_t) record->data[3] << 8) |
     103                                                ((uint32_t) record->data[4] << 16) | ((uint32_t) record->data[5] << 24);
     104                        if (record->size == bmp_size) {
     105                                if (broken_cover) {
     106                                        printf(
     107                                            "Resource record %u did not appear to be the cover image (it's a bmp). . .\n",
     108                                            record->uid);
     109                                        continue;
     110                                }
     111                                snprintf(ext, sizeof(ext), "%s", "bmp");
     112                                cover_found = true;
     113                                break;
     114                        }
     115                } else {
     116                        printf("Cover not found in record %u\n", record->uid);
     117                        continue;
     118                }
     119        }
     120
     121        if (!cover_found) {
     122                printf("Unable to find a cover!\n");
     123                return ERRCODE(EXIT_FAILURE);
     124        }
     125
     126        char dirname[FILENAME_MAX];
     127        char basename[FILENAME_MAX];
     128        split_fullpath(fullpath, dirname, basename);
     129
     130        char* asin   = mobi_meta_get_asin(m);
     131        char* cdekey = NULL;
     132        if (asin) {
     133                cdekey = asin;
     134        } else {
     135                // Use the sha1 of the full path, like the Kindle
     136                char abspath[PATH_MAX];
     137                (void) realpath(fullpath, abspath);
     138
     139                unsigned char hash[SHA1_DIGEST_SIZE];
     140                SHA1_CTX      ctx;
     141                SHA1_Init(&ctx);
     142                SHA1_Update(&ctx, abspath, strlen(abspath));
     143                SHA1_Final(&ctx, hash);
     144
     145                // c.f., https://git.lysator.liu.se/nettle/nettle/-/blob/master/base16-encode.c
     146                static const uint8_t hex_digits[16] = "0123456789abcdef";
     147#define DIGIT(x) (hex_digits[(x) &0xf])
     148                char     hex_hash[SHA1_DIGEST_SIZE * 2] = { 0 };
     149                uint8_t* src                            = hash;
     150                char*    dst                            = hex_hash;
     151                for (size_t i = 0; i < SHA1_DIGEST_SIZE; i++, dst += 2) {
     152                        dst[0] = DIGIT(src[i] / 0x10);
     153                        dst[1] = DIGIT(src[i]);
     154                }
     155
     156                cdekey = hex_hash;
     157        }
     158        char cover_path[FILENAME_MAX];
     159        if (outdir_opt) {
     160                snprintf(cover_path, sizeof(cover_path), "%scover_raw_%s.%s", outdir, cdekey, ext);
     161        } else {
     162                snprintf(cover_path, sizeof(cover_path), "%scover_raw_%s.%s", dirname, cdekey, ext);
     163        }
     164        free(asin);
     165
     166        printf("Saving cover to %s\n", cover_path);
     167        errno      = 0;
     168        FILE* file = fopen(cover_path, "wb");
     169        if (file == NULL) {
     170                int errsv = errno;
     171                printf("Could not open file for writing: %s (%s)\n", cover_path, strerror(errsv));
     172                return ERRCODE(EXIT_FAILURE);
     173        }
     174        size_t count = fwrite(record->data, 1, record->size, file);
     175        if (count != record->size) {
     176                int errsv = errno;
     177                printf("Error writing to file: %s (%s)\n", cover_path, strerror(errsv));
     178                fclose(file);
     179                return ERRCODE(EXIT_FAILURE);
     180        }
     181        fclose(file);
     182
     183        return EXIT_SUCCESS;
    174184}
    175 
    176185
    177186// Help message
     
    192201            "\t-o, --outdir\t\t\tUse a spercific output directory, instead of the input file's.\n"
    193202            "\n",
    194             VERSION, mobi_version());
     203            VERSION,
     204            mobi_version());
    195205        return;
    196206}
     
    199209 @brief Main
    200210 */
    201 int main(int argc, char* argv[]) {
     211int
     212    main(int argc, char* argv[])
     213{
    202214        int                        opt;
    203215        int                        opt_index;
     
    207219                                              { NULL, 0, NULL, 0 } };
    208220
    209         bool     errfnd      = false;
    210         char *outdir = NULL;
    211         bool do_typecheck = false;
     221        bool  errfnd       = false;
     222        char* outdir      = NULL;
     223        bool  do_typecheck = false;
    212224
    213225        while ((opt = getopt_long(argc, argv, "o:hk", opts, &opt_index)) != -1) {
     
    245257                        /* Initialize main MOBIData structure */
    246258                        /* Must be deallocated with mobi_free() when not needed */
    247                         MOBIData *m = mobi_init();
     259                        MOBIData* m = mobi_init();
    248260                        if (m == NULL) {
    249261                                fprintf(strerror, "Memory allocation failed\n");
     
    252264
    253265                        /* Open file for reading */
    254                         FILE *file = fopen(infile, "rb");
     266                        FILE* file = fopen(infile, "rb");
    255267                        if (file == NULL) {
    256268                                fprintf(strerror, "Error opening file: %s (fopen: %m)\n", infile);
Note: See TracChangeset for help on using the changeset viewer.