Added a tool for encoding/decoding Base64.

This commit is contained in:
Moritz Bunkus 2003-07-30 20:28:14 +00:00
parent 1396beb59f
commit 480640f014
6 changed files with 323 additions and 7 deletions

View File

@ -686,7 +686,7 @@ Matroska element.
Otherwise the data is expected to be \fIBase64\fR encoded. This is an
encoding that transforms binary data into a limited set of ASCII
characters and is used e.g. in email programs. \fBmkvtoolnix\fR comes
with a utility, \fBbase64util\fR, that can be used to encode to and
with a utility, \fBbase64tool\fR, that can be used to encode to and
decode from Base64. \fBmkvextract\fR will output Base64 encoded data
for binary elements.

View File

@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = dist-zip foreign
bin_PROGRAMS = mkvmerge mkvinfo mkvextract
bin_PROGRAMS = mkvmerge mkvinfo mkvextract base64tool
mkvmerge_SOURCES = mkvmerge.cpp mkvmerge.h \
aac_common.cpp aac_common.h \
@ -53,6 +53,11 @@ mkvextract_SOURCES = mkvextract.cpp \
mm_io.cpp mm_io.h \
tagwriter.cpp tagwriter.h
base64tool_SOURCES = base64tool.cpp \
base64.cpp base64.h \
common.cpp common.h \
mm_io.cpp mm_io.h
mkvmerge_LDADD = @AVILIB_LIBS@ @PROFILING_LIBS@ \
@MATROSKA_LIBS@ @EBML_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ \
@ICONV_LIBS@ @MINGW_LIBS@ @EXPAT_LIBS@ -lexpat
@ -63,3 +68,5 @@ mkvinfo_LDADD = @PROFILING_LIBS@ @MATROSKA_LIBS@ @EBML_LIBS@ @ICONV_LIBS@ \
mkvextract_LDADD = @AVILIB_LIBS@ @PROFILING_LIBS@ @MATROSKA_LIBS@ @EBML_LIBS@ \
@VORBIS_LIBS@ @OGG_LIBS@ @ICONV_LIBS@
base64tool_LDADD = @EBML_LIBS@ @ICONV_LIBS@

139
src/base64tool.cpp Normal file
View File

@ -0,0 +1,139 @@
/*
base64util - Utility for encoding and decoding Base64 files.
base64util.cpp
Written by Moritz Bunkus <moritz@bunkus.org>
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version $Id$
\brief command line parameter parsing, looping, output handling
\author Moritz Bunkus <moritz@bunkus.org>
*/
#include <errno.h>
#include <string.h>
#include <string>
#include "os.h"
#include "base64.h"
#include "common.h"
#include "mm_io.h"
using namespace std;
void usage(int retval) {
mxprint(stdout,
"base64util <encode|decode> <input> <output> [maxlen]\n"
"\n"
" encode - Read from <input>, encode to Base64 and write to <output>.\n"
" Max line length can be specified and is 72 if left out.\n"
" decode - Read from <input>, decode to binary and write to <output>.\n");
exit(retval);
}
int main(int argc, char *argv[]) {
int maxlen;
int64_t size;
unsigned char *buffer;
char mode;
string s, line;
mm_io_c *in, *out;
mm_text_io_c *intext;
if (argc < 4)
usage(0);
if (!strcmp(argv[1], "encode"))
mode = 'e';
else if (!strcmp(argv[1], "decode"))
mode = 'd';
else {
mxprint(stdout, "Error: invalid mode '%s'.\n\n", argv[1]);
usage(1);
}
maxlen = 72;
if ((argc == 5) && (mode == 'e')) {
if (!parse_int(argv[4], maxlen) || (maxlen < 4)) {
mxprint(stdout, "Error: Max line length must be >= 4.\n\n");
exit(1);
}
} else if ((argc > 5) || ((argc > 4) && (mode == 'd')))
usage(1);
maxlen = ((maxlen + 3) / 4) * 4;
try {
if (mode == 'e')
in = new mm_io_c(argv[2], MODE_READ);
else {
intext = new mm_text_io_c(argv[2]);
in = intext;
}
} catch(...) {
mxprint(stdout, "Error: Could not open '%s' for reading (%d, %s).\n",
argv[2], errno, strerror(errno));
exit(1);
}
try {
out = new mm_io_c(argv[3], MODE_WRITE);
} catch(...) {
mxprint(stdout, "Error: Could not open '%s' for writing (%d, %s).\n",
argv[3], errno, strerror(errno));
exit(1);
}
in->save_pos();
in->setFilePointer(0, seek_end);
size = in->getFilePointer();
in->restore_pos();
if (mode == 'e') {
buffer = (unsigned char *)safemalloc(size);
size = in->read(buffer, size);
delete in;
s = base64_encode(buffer, size, true, maxlen);
safefree(buffer);
out->write(s.c_str(), s.length());
delete out;
} else {
while (intext->getline2(line)) {
strip(line);
s += line;
}
delete intext;
buffer = (unsigned char *)safemalloc(s.length() / 4 * 3 + 100);
try {
size = base64_decode(s, buffer);
} catch(...) {
mxprint(stdout, "Error decoding data.\n");
delete in;
delete out;
exit(1);
}
out->write(buffer, size);
safefree(buffer);
delete out;
}
mxprint(stdout, "Done.\n");
return 0;
}

View File

@ -339,3 +339,157 @@ void write_chapters_xml(KaxChapters *chapters, FILE *out) {
}
}
}
class chapter_entry_c {
public:
string name;
int64_t start, level;
chapter_entry_c(string n, int64_t s, int64_t l);
bool operator < (const chapter_entry_c &cmp) const;
};
chapter_entry_c::chapter_entry_c(string n, int64_t s, int64_t l) {
name = n;
start = s;
level = l;
}
bool chapter_entry_c::operator <(const chapter_entry_c &cmp) const {
return start < cmp.start;
}
static vector<chapter_entry_c> chapter_start_times, chapter_names,
chapter_entries;
static void handle_name(int level, const char *name) {
int i, j;
vector<chapter_entry_c>::iterator itr;
for (i = 0; i < chapter_start_times.size(); i++) {
chapter_entry_c &e = chapter_start_times[i];
if (e.level == level) {
chapter_entries.push_back(chapter_entry_c(string(name), e.start, level));
itr = chapter_start_times.begin();
for (j = 0; j < i; j++)
itr++;
chapter_start_times.erase(itr);
return;
}
}
chapter_names.push_back(chapter_entry_c(name, 0, level));
}
static void handle_start_time(int level, int64_t start_time) {
int i, j;
vector<chapter_entry_c>::iterator itr;
for (i = 0; i < chapter_names.size(); i++) {
chapter_entry_c &e = chapter_names[i];
if (e.level == level) {
chapter_entries.push_back(chapter_entry_c(e.name, start_time, level));
itr = chapter_names.begin();
for (j = 0; j < i; j++)
itr++;
chapter_names.erase(itr);
return;
}
}
chapter_start_times.push_back(chapter_entry_c("", start_time, level));
}
static void write_chapter_atom_simple(KaxChapterAtom *atom, int level);
static void write_chapter_display_simple(KaxChapterDisplay *display,
int level) {
int i;
EbmlElement *e;
char *s;
for (i = 0; i < display->ListSize(); i++) {
e = (*display)[i];
if (is_id(KaxChapterString)) {
s = UTFstring_to_cstrutf8(UTFstring(*static_cast
<EbmlUnicodeString *>(e)).c_str());
handle_name(level - 1, s);
safefree(s);
} else if (is_id(KaxChapterAtom))
write_chapter_atom_simple((KaxChapterAtom *)e, level + 1);
}
}
static void write_chapter_track_simple(KaxChapterTrack *track, int level) {
int i;
EbmlElement *e;
for (i = 0; i < track->ListSize(); i++) {
e = (*track)[i];
if (is_id(KaxChapterAtom))
write_chapter_atom_simple((KaxChapterAtom *)e, level + 1);
}
}
static void write_chapter_atom_simple(KaxChapterAtom *atom, int level) {
int i;
EbmlElement *e;
uint64_t v;
for (i = 0; i < atom->ListSize(); i++) {
e = (*atom)[i];
if (is_id(KaxChapterTimeStart)) {
v = uint64(*static_cast<EbmlUInteger *>(e)) / 1000000;
handle_start_time(level, level);
} else if (is_id(KaxChapterTrack))
write_chapter_track_simple((KaxChapterTrack *)e, level + 1);
else if (is_id(KaxChapterDisplay))
write_chapter_display_simple((KaxChapterDisplay *)e, level + 1);
else if (is_id(KaxChapterAtom))
write_chapter_atom_simple((KaxChapterAtom *)e, level + 1);
}
}
void write_chapters_simple(int &chapter_num, KaxChapters *chapters,
FILE *out) {
int i, j;
int64_t v;
KaxEditionEntry *edition;
chapter_start_times.clear();
chapter_names.clear();
chapter_entries.clear();
for (i = 0; i < chapters->ListSize(); i++) {
if (is_id2((*chapters)[i], KaxEditionEntry)) {
edition = (KaxEditionEntry *)(*chapters)[i];
for (j = 0; j < edition->ListSize(); j++)
if (is_id2((*edition)[j], KaxChapterAtom))
write_chapter_atom_simple((KaxChapterAtom *)(*edition)[j], 2);
}
}
for (i = 0; i < chapter_entries.size(); i++) {
v = chapter_entries[i].start;
mxprint(out, "CHAPTER%02d=%02lld:%02lld:%02lld.%03lld\n", chapter_num,
(v / 1000 / 60 / 60), (v / 1000 / 60) % 60,
(v / 1000) % 60, v % 1000);
mxprint(out, "CHAPTER%02dNAME=%s\n", chapter_num,
chapter_entries[i].name.c_str());
chapter_num++;
}
chapter_start_times.clear();
chapter_names.clear();
chapter_entries.clear();
}

View File

@ -31,6 +31,7 @@ KaxChapters *parse_chapters(const char *file_name, int64_t min_tc = 0,
int64_t max_tc = -1, int64_t offset = 0);
void write_chapters_xml(KaxChapters *chapters, FILE *out);
void write_chapters_simple(int &chapter_num, KaxChapters *chapters, FILE *out);
#endif // __CHAPTERS_H

View File

@ -137,6 +137,7 @@ typedef struct {
} kax_track_t;
vector<kax_track_t> tracks;
bool chapter_format_simple = false;
kax_track_t *find_track(int tid) {
int i;
@ -176,9 +177,11 @@ void usage() {
" Third mode extracts attachments from inname.\n"
" AID:outname Write the attachment with the ID AID to 'outname'.\n"
"\n"
" Second mode extracts the chapters and converts them to XML. The output is\n"
" Fourth mode extracts the chapters and converts them to XML. The output is\n"
" written to the standard output. The output can be used as a source\n"
" for mkvmerge.\n"
" -s, --simple Exports the chapter infomartion in the simple format\n"
" used in OGM tools (CHAPTER01=... CHAPTER01NAME=...).\n"
"\n"
" These options can be used instead of the mode keyword to obtain\n"
" further information:\n"
@ -251,11 +254,19 @@ void parse_args(int argc, char **argv, char *&file_name, int &mode) {
conv_handle = utf8_init(argv[i + 1]);
i++;
} else if ((mode == MODE_TAGS) || (mode == MODE_CHAPTERS)) {
} else if (mode == MODE_TAGS) {
mxprint(stderr, "Error: No further options allowed when extracting "
"%s.\n", argv[1]);
exit(1);
} else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--simple")) {
if (mode != MODE_CHAPTERS) {
mxprint(stderr, "Error: %s is only allowed for chapter extraction.\n",
argv[i]);
exit(1);
}
chapter_format_simple = true;
} else {
copy = safestrdup(argv[i]);
colon = strchr(copy, ':');
@ -1580,6 +1591,7 @@ void extract_chapters(const char *file_name) {
EbmlStream *es;
mm_io_c *in;
bool chapters_extracted = false;
int next_chapter = 1;
// open input file
try {
@ -1640,12 +1652,15 @@ void extract_chapters(const char *file_name) {
chapters.Read(*es, KaxChapters::ClassInfos.Context, upper_lvl_el, l2,
true);
if (!chapters_extracted) {
if (!chapters_extracted && !chapter_format_simple) {
mxprint(stdout, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"
"<Chapters>\n");
chapters_extracted = true;
}
if (chapter_format_simple)
write_chapters_simple(next_chapter, &chapters, stdout);
else
write_chapters_xml(&chapters, stdout);
} else
@ -1683,7 +1698,7 @@ void extract_chapters(const char *file_name) {
return;
}
if (chapters_extracted)
if (chapters_extracted && !chapter_format_simple)
mxprint(stdout, "</Chapters>\n");
}