• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2012 Stefano Sabatini
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "config.h"
22 #include <errno.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #if HAVE_UNISTD_H
28 #include <unistd.h>             /* getopt */
29 #endif
30 
31 #include "libavutil/log.h"
32 #include "libavutil/bprint.h"
33 #include "libavutil/mem.h"
34 
35 #if !HAVE_GETOPT
36 #include "compat/getopt.c"
37 #endif
38 
39 /**
40  * @file
41  * escaping utility
42  */
43 
usage(void)44 static void usage(void)
45 {
46     printf("Escape an input string, adopting the av_get_token() escaping logic\n");
47     printf("usage: ffescape [OPTIONS]\n");
48     printf("\n"
49            "Options:\n"
50            "-e                echo each input line on output\n"
51            "-f flag           select an escape flag, can assume the values 'whitespace' and 'strict'\n"
52            "-h                print this help\n"
53            "-i INFILE         set INFILE as input file, stdin if omitted\n"
54            "-l LEVEL          set the number of escaping levels, 1 if omitted\n"
55            "-m ESCAPE_MODE    select escape mode between 'auto', 'backslash', 'quote'\n"
56            "-o OUTFILE        set OUTFILE as output file, stdout if omitted\n"
57            "-p PROMPT         set output prompt, is '=> ' by default\n"
58            "-s SPECIAL_CHARS  set the list of special characters\n");
59 }
60 
main(int argc,char ** argv)61 int main(int argc, char **argv)
62 {
63     AVBPrint src;
64     char *src_buf, *dst_buf;
65     const char *outfilename = NULL, *infilename = NULL;
66     FILE *outfile = NULL, *infile = NULL;
67     const char *prompt = "=> ";
68     enum AVEscapeMode escape_mode = AV_ESCAPE_MODE_AUTO;
69     int escape_flags = 0;
70     int level = 1;
71     int echo = 0;
72     char *special_chars = NULL;
73     int c;
74 
75     while ((c = getopt(argc, argv, "ef:hi:l:o:m:p:s:")) != -1) {
76         switch (c) {
77         case 'e':
78             echo = 1;
79             break;
80         case 'h':
81             usage();
82             return 0;
83         case 'i':
84             infilename = optarg;
85             break;
86         case 'f':
87             if      (!strcmp(optarg, "whitespace"))        escape_flags |= AV_ESCAPE_FLAG_WHITESPACE;
88             else if (!strcmp(optarg, "strict"))            escape_flags |= AV_ESCAPE_FLAG_STRICT;
89             else if (!strcmp(optarg, "xml_single_quotes")) escape_flags |= AV_ESCAPE_FLAG_XML_SINGLE_QUOTES;
90             else if (!strcmp(optarg, "xml_double_quotes")) escape_flags |= AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES;
91             else {
92                 av_log(NULL, AV_LOG_ERROR,
93                        "Invalid value '%s' for option -f, "
94                        "valid arguments are 'whitespace', and 'strict'\n", optarg);
95                 return 1;
96             }
97             break;
98         case 'l':
99         {
100             char *tail;
101             long int li = strtol(optarg, &tail, 10);
102             if (*tail || li > INT_MAX || li < 0) {
103                 av_log(NULL, AV_LOG_ERROR,
104                         "Invalid value '%s' for option -l, argument must be a non negative integer\n",
105                         optarg);
106                 return 1;
107             }
108             level = li;
109             break;
110         }
111         case 'm':
112             if      (!strcmp(optarg, "auto"))      escape_mode = AV_ESCAPE_MODE_AUTO;
113             else if (!strcmp(optarg, "backslash")) escape_mode = AV_ESCAPE_MODE_BACKSLASH;
114             else if (!strcmp(optarg, "quote"))     escape_mode = AV_ESCAPE_MODE_QUOTE;
115             else if (!strcmp(optarg, "xml"))       escape_mode = AV_ESCAPE_MODE_XML;
116             else {
117                 av_log(NULL, AV_LOG_ERROR,
118                        "Invalid value '%s' for option -m, "
119                        "valid arguments are 'backslash', and 'quote'\n", optarg);
120                 return 1;
121             }
122             break;
123         case 'o':
124             outfilename = optarg;
125             break;
126         case 'p':
127             prompt = optarg;
128             break;
129         case 's':
130             special_chars = optarg;
131             break;
132         case '?':
133             return 1;
134         }
135     }
136 
137     if (!infilename || !strcmp(infilename, "-")) {
138         infilename = "stdin";
139         infile = stdin;
140     } else {
141         infile = fopen(infilename, "r");
142     }
143     if (!infile) {
144         av_log(NULL, AV_LOG_ERROR, "Impossible to open input file '%s': %s\n", infilename, strerror(errno));
145         return 1;
146     }
147 
148     if (!outfilename || !strcmp(outfilename, "-")) {
149         outfilename = "stdout";
150         outfile = stdout;
151     } else {
152         outfile = fopen(outfilename, "w");
153     }
154     if (!outfile) {
155         av_log(NULL, AV_LOG_ERROR, "Impossible to open output file '%s': %s\n", outfilename, strerror(errno));
156         return 1;
157     }
158 
159     /* grab the input and store it in src */
160     av_bprint_init(&src, 1, AV_BPRINT_SIZE_UNLIMITED);
161     while ((c = fgetc(infile)) != EOF)
162         av_bprint_chars(&src, c, 1);
163     av_bprint_chars(&src, 0, 1);
164 
165     if (!av_bprint_is_complete(&src)) {
166         av_log(NULL, AV_LOG_ERROR, "Could not allocate a buffer for the source string\n");
167         av_bprint_finalize(&src, NULL);
168         return 1;
169     }
170     av_bprint_finalize(&src, &src_buf);
171 
172     if (echo)
173         fprintf(outfile, "%s", src_buf);
174 
175     /* escape */
176     dst_buf = src_buf;
177     while (level--) {
178         if (av_escape(&dst_buf, src_buf, special_chars, escape_mode, escape_flags) < 0) {
179             av_log(NULL, AV_LOG_ERROR, "Could not escape string\n");
180             return 1;
181         }
182         av_free(src_buf);
183         src_buf = dst_buf;
184     }
185 
186     fprintf(outfile, "%s%s", prompt, dst_buf);
187     av_free(dst_buf);
188     return 0;
189 }
190