2 * "THE BEER-WARE LICENSE" (Revision 42):
3 * <tobias.rehbein@web.de> wrote this file. As long as you retain this notice
4 * you can do whatever you want with this stuff. If we meet some day, and you
5 * think this stuff is worth it, you can buy me a beer in return.
17 #include <vorbis/vorbisfile.h>
27 struct chk_conditions
*cond
;
28 struct element
*regexlist
;
43 static bool check_bitrate(struct oggfile
*of
, struct chk_context
*ctx
);
44 static bool check_comments(struct oggfile
*of
, struct chk_context
*ctx
);
45 static bool check_time(struct oggfile
*of
, struct chk_context
*ctx
);
46 static int oggfile_close(struct oggfile
*of
);
47 static int oggfile_open(struct oggfile
*of
, char *path
);
50 chk_check_file(char *path
, struct chk_context
*ctx
)
56 if (oggfile_open(&of
, path
) != 0) {
57 warn("oggfile_open \"%s\"", path
);
61 bool match
= check_time(&of
, ctx
);
62 match
= match
&& check_bitrate(&of
, ctx
);
63 match
= match
&& check_comments(&of
, ctx
);
65 if (oggfile_close(&of
) != 0)
66 warn("oggfile_close \"%s\"", path
);
72 chk_init_conditions(struct chk_conditions
*cond
)
76 cond
->min_length
= -1;
77 cond
->max_length
= -1;
78 cond
->min_bitrate
= -1;
79 cond
->max_bitrate
= -1;
80 cond
->regexlist
= NULL
;
84 chk_context_open(struct chk_conditions
*cond
)
88 struct chk_context
*ctx
= malloc(sizeof(*ctx
));
90 err(EXIT_FAILURE
, "malloc chk_context");
91 if ((ctx
->cd
= iconv_open("", "UTF-8")) == (iconv_t
) (-1))
92 err(EXIT_FAILURE
, "iconv_open");
94 ctx
->regexlist
= NULL
;
96 for (struct element
*e
= cond
->regexlist
; e
!= NULL
; e
= e
->next
) {
97 struct regex
*re
= malloc(sizeof(*re
));
99 err(EXIT_FAILURE
, "malloc regex");
101 struct chk_expression
*cx
= e
->payload
;
102 re
->invert
= cx
->invert
;
103 re
->pattern
= cx
->expression
;
104 if ((re
->regex
= malloc(sizeof(*(re
->regex
))))== NULL
)
105 err(EXIT_FAILURE
, "malloc regex_t");
107 int flags
= REG_EXTENDED
;
108 if (!cond
->noignorecase
)
111 int errcode
= regcomp(re
->regex
, re
->pattern
, flags
);
114 regerror(errcode
, re
->regex
, errstr
, sizeof(errstr
));
115 errx(EXIT_FAILURE
, "regcomp \"%s\": %s", re
->pattern
, errstr
);
118 struct element
*ne
= create_element(re
);
120 err(EXIT_FAILURE
, "create_element regex");
121 ctx
->regexlist
= prepend_element(ne
, ctx
->regexlist
);
128 chk_context_close(struct chk_context
*ctx
)
132 if (iconv_close(ctx
->cd
) == -1)
135 while (ctx
->regexlist
!= NULL
) {
136 struct regex
*r
= ctx
->regexlist
->payload
;
139 ctx
->regexlist
= destroy_element(ctx
->regexlist
);
147 oggfile_open(struct oggfile
*of
, char *path
)
150 assert(path
!= NULL
);
152 if (ov_fopen((char *)path
, &of
->ovf
) != 0)
161 oggfile_close(struct oggfile
*of
)
165 if (ov_clear(&of
->ovf
) != 0)
174 check_time(struct oggfile
*of
, struct chk_context
*ctx
)
179 double time
= ov_time_total(&of
->ovf
, -1);
180 if (time
== OV_EINVAL
) {
181 warnx("ov_time_total \"%s\"", of
->path
);
185 double min_length
= ctx
->cond
->min_length
;
186 if (min_length
>= 0 && min_length
> time
)
189 double max_length
= ctx
->cond
->max_length
;
190 if (max_length
>= 0 && max_length
< time
)
197 check_bitrate(struct oggfile
*of
, struct chk_context
*ctx
)
202 vorbis_info
*ovi
= ov_info(&of
->ovf
, -1);
204 warnx("ov_info \"%s\"", of
->path
);
208 long nominal
= ovi
->bitrate_nominal
;
210 long min_bitrate
= ctx
->cond
->min_bitrate
;
211 if (min_bitrate
>= 0 && min_bitrate
> nominal
)
214 long max_bitrate
= ctx
->cond
->max_bitrate
;
215 if (max_bitrate
>= 0 && max_bitrate
< nominal
)
222 check_comments(struct oggfile
*of
, struct chk_context
*ctx
)
227 vorbis_comment
*ovc
= NULL
;
228 if ((ovc
= ov_comment(&of
->ovf
, -1)) == NULL
) {
229 warnx("ov_comment \"%s\"", of
->path
);
232 for (struct element
*e
= ctx
->regexlist
; e
!= NULL
; e
= e
->next
) {
234 struct regex
*re
= e
->payload
;
236 for (int i
= 0; i
< ovc
->comments
; i
++) {
237 char *comment
, *conv_comment
;
238 if ((conv_comment
= malloc(COMMENTLEN
)) == NULL
)
239 err(EXIT_FAILURE
, "malloc(%d)", COMMENTLEN
);
240 comment
= ovc
->user_comments
[i
];
242 const char *from
= comment
;
243 char *to
= conv_comment
;
244 size_t fromlen
= strlen(comment
);
245 size_t tolen
= COMMENTLEN
;
247 if (iconv(ctx
->cd
, NULL
, NULL
, &to
, &tolen
) == (size_t) (-1))
248 err(EXIT_FAILURE
, "reset iconv descriptor");
250 if (iconv(ctx
->cd
, &from
, &fromlen
, &to
, &tolen
) == (size_t) (-1)) {
251 warn("iconv \"%s\"", ovc
->user_comments
[i
]);
257 if (regexec(re
->regex
, conv_comment
, 0, NULL
, 0)== 0)
263 assert(match
== 0 || match
== 1);
264 assert(re
->invert
== 0 || re
->invert
== 1);
265 if (!match
^ re
->invert
)