#ifdef _WIN32
#else
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif
#ifdef USE_ENCRYPTION
# define PRINT_ENC_USG " [-p pid] [-P serial]"
# define PRINT_ENC_ARG "p:P:"
#else
# define PRINT_ENC_USG ""
# define PRINT_ENC_ARG ""
#endif
#ifdef USE_ENCRYPTION
int setpid_opt = 0;
int setserial_opt = 0;
#endif
#ifdef USE_ENCRYPTION
char *pid = NULL;
char *serial = NULL;
#endif
#define META_SIZE ARRAYSIZE(meta_functions)
#define ACTIONS_SIZE ARRAYSIZE(actions)
typedef struct {
const char *name;
MetaFunDel function_del;
const CB meta_functions[] = {
};
char *p = strrchr(progname, separator);
if (p) { progname = ++p; }
printf("usage: %s [-a | -s meta=value[,meta=value,...]] [-d meta[,meta,...]]" PRINT_ENC_USG " [-v] filein [fileout]\n", progname);
printf(" without arguments prints document metadata and exits\n");
printf(" -a ? list valid meta named keys\n");
printf(" -a meta=value add metadata\n");
printf(" -d meta delete metadata\n");
printf(" -s meta=value set metadata\n");
#ifdef USE_ENCRYPTION
printf(" -p pid set pid for decryption\n");
printf(" -P serial set device serial for decryption\n");
#endif
printf(" -v show version and exit\n");
exit(ERROR);
}
if (*string == '\0') { return false; }
while (*string) {
if (!isdigit(*string++)) { return false; }
}
return true;
}
bool parsesubopt(
char **subopts,
char **token,
char **value) {
if (!**subopts) { return -1; }
*token = NULL;
*value = NULL;
char *p = NULL;
while ((p = (*subopts)++) && *p) {
if (*p == ',') {
*p = '\0';
return true;
}
if (!*token) { *token = p; }
if (*p == '=') {
*p = '\0';
*value = ++p;
}
}
return false;
}
for (int i = 0; i < (int) META_SIZE; i++) {
if (strcmp(token, meta_functions[i].name) == 0) {
return i;
}
}
return -1;
}
int main(
int argc,
char *argv[]) {
if (argc < 2) {
}
typedef struct {
int command;
int meta;
char *value;
} Action;
Action actions[100];
size_t cmd_count = 0;
char *token = NULL;
char *value = NULL;
char *subopts;
int opt;
int subopt;
bool parse;
while ((opt = getopt(argc, argv, "a:d:s:" PRINT_ENC_ARG "v")) != -1) {
switch (opt) {
case 'a':
case 'd':
case 's':
subopts = optarg;
parse = true;
while (parse) {
if ((value == NULL || strlen(value) == 0) && opt != 'd') {
printf("Missing value for suboption '%s'\n\n", meta_functions[subopt].name);
}
if (cmd_count < (ACTIONS_SIZE)) {
actions[cmd_count++] = (Action) { opt, subopt, value };
}
if ((value == NULL || strlen(value) == 0) && opt != 'd') {
printf("Missing value for suboption '%s'\n\n", token);
}
if (cmd_count < (ACTIONS_SIZE)) {
actions[cmd_count++] = (Action) { toupper(opt), atoi(token), value };
}
} else {
if (token[0] != '?') {
printf("Unknown meta: %s\n", token);
}
printf("Valid named meta keys:\n");
for (size_t i = 0; i < META_SIZE; i++) {
printf(" %s\n", meta_functions[i].name);
}
printf("\n");
if (token[0] != '?') {
}
return SUCCESS;
}
}
break;
#ifdef USE_ENCRYPTION
case 'p':
setpid_opt = 1;
pid = optarg;
break;
case 'P':
setserial_opt = 1;
serial = optarg;
break;
#endif
case 'v':
printf("mobimeta build: " __DATE__ " " __TIME__ " (" COMPILER ")\n");
return 0;
case '?':
#ifdef USE_ENCRYPTION
if (optopt == 'p') {
printf("Option -%c requires an argument.\n", optopt);
}
else
#endif
if (isprint(optopt)) {
printf("Unknown option `-%c'\n", optopt);
}
else {
printf("Unknown option character `\\x%x'\n", optopt);
}
break;
default:
}
}
int file_args = argc - optind;
if (file_args <= 0) {
printf("Missing filename\n");
}
char infile[FILENAME_MAX];
strncpy(infile, argv[optind], FILENAME_MAX - 1);
infile[FILENAME_MAX - 1] = '\0';
if (file_args >= 2) { optind++; }
char outfile[FILENAME_MAX];
strncpy(outfile, argv[optind], FILENAME_MAX - 1);
outfile[FILENAME_MAX - 1] = '\0';
if (m == NULL) {
printf("Libmobi initialization failed\n");
return ERROR;
}
FILE *file_in = fopen(infile, "rb");
if (file_in == NULL) {
int errsv = errno;
printf("Error opening file: %s (%s)\n", infile, strerror(errsv));
return ERROR;
}
fclose(file_in);
printf(
"Error loading file (%s)\n",
libmobi_msg(mobi_ret));
return ERROR;
}
#ifdef USE_ENCRYPTION
if (setpid_opt || setserial_opt) {
if (ret != SUCCESS) {
return ret;
};
}
#endif
if (cmd_count == 0) {
return SUCCESS;
}
for (size_t i = 0; i < cmd_count; i++) {
Action action = actions[i];
switch (action.command) {
case 'a':
mobi_ret = meta_functions[action.meta].
function_add(m, action.value);
break;
case 'd':
mobi_ret = meta_functions[action.meta].
function_del(m);
break;
case 's':
mobi_ret = meta_functions[action.meta].
function_set(m, action.value);
break;
case 'A':
uint32_t numeric = (uint32_t) atoi(action.value);
} else {
}
break;
case 'D':
break;
case 'S':
uint32_t numeric = (uint32_t) atoi(action.value);
} else {
}
break;
}
printf(
"Metadata modification failed (%s)\n",
libmobi_msg(mobi_ret));
return ERROR;
}
}
printf("Saving %s...\n", outfile);
FILE *file_out = fopen(outfile, "wb");
if (file_out == NULL) {
int errsv = errno;
printf("Error opening file: %s (%s)\n", outfile, strerror(errsv));
return ERROR;
}
fclose(file_out);
printf(
"Error writing file (%s)\n",
libmobi_msg(mobi_ret));
return ERROR;
}
return SUCCESS;
}