1 /*
2  * Copyright (c) 2009-2020 Kuan-Chung Chiu <buganini@gmail.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include "php.h"
31 #include "php_ini.h"
32 #include "zend_exceptions.h"
33 #include "ext/standard/info.h"
34 #include "php_bsdconv.h"
35 
36 #ifndef WIN32
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #endif
41 
42 #include <bsdconv.h>
43 
44 #if PHP_MAJOR_VERSION < 7
45 typedef int str_size_t;
46 #define _COMPAT_RETVAL_STRINGL(s) RETVAL_STRING(s, 1)
47 #else
48 typedef size_t str_size_t;
49 #define _COMPAT_RETVAL_STRINGL(s) RETVAL_STRINGL(s, strlen(s))
50 #define zend_rsrc_list_entry zend_resource
51 #define zend_object_store_get_object(x, ...) ((char*)Z_OBJ_P(x) - XtOffsetOf(struct bsdconv_object, std))
52 #endif
53 
54 #if PHP_MAJOR_VERSION >= 8
55 #define TSRMLS_DC
56 #define TSRMLS_CC
57 #define ZEND_ACC_DTOR 0
58 ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0)
59 ZEND_END_ARG_INFO()
60 #else
61 #define arginfo_void NULL
62 #endif
63 
64 /* True global resources - no need for thread safety here */
65 static int le_bsdconv_fp;
66 
bsdconv_fp_dtor(zend_rsrc_list_entry * rsrc TSRMLS_DC)67 static void bsdconv_fp_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC){
68 	fclose((FILE *) rsrc->ptr);
69 }
70 
71 zend_class_entry *bsdconv_ce;
72 
73 zend_object_handlers bsdconv_object_handlers;
74 
75 #if PHP_MAJOR_VERSION < 7
76 struct bsdconv_object {
77 	zend_object std;
78 	struct bsdconv_instance *ins;
79 };
80 #else
81 struct bsdconv_object {
82 	struct bsdconv_instance *ins;
83 	zend_object std;
84 };
85 #endif
86 
87 #define IBUFLEN 1024
88 
bsdconv_dtor(zend_rsrc_list_entry * rsrc TSRMLS_DC)89 static void bsdconv_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC){
90 	bsdconv_destroy((struct bsdconv_instance *) rsrc->ptr);
91 }
92 
93 /* {{{ proto resource __construct(string conversion)
94   create bsdconv instance */
PHP_METHOD(Bsdconv,__construct)95 PHP_METHOD(Bsdconv,  __construct){
96 	char *c;
97 	str_size_t l;
98 
99 	struct bsdconv_instance *ins;
100 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &c, &l) == FAILURE){
101 		return;
102 	}
103 	ins=bsdconv_create(c);
104 	if(ins==NULL){
105 		zend_throw_exception(NULL, "Failed constructing bsdconv", 0);
106 		return;
107 	}
108 	struct bsdconv_object *obj = (struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
109 	obj->ins = ins;
110 }
111 /* }}} */
112 
113 /* {{{ proto int __destruct()
114   destroy bsdconv instance */
PHP_METHOD(Bsdconv,__destruct)115 PHP_METHOD(Bsdconv, __destruct){
116 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
117 	struct bsdconv_instance *ins=obj->ins;
118 	bsdconv_destroy(ins);
119 	RETURN_BOOL(1);
120 }
121 
122 /* }}} */
123 /* {{{ proto void init()
124   initialize/reset bsdconv instance */
PHP_METHOD(Bsdconv,init)125 PHP_METHOD(Bsdconv, init){
126 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
127 	struct bsdconv_instance *ins=obj->ins;
128 	bsdconv_init(ins);
129 }
130 /* }}} */
131 
132 /* {{{ proto mixed ctl(int ctl, resource res, int num)
133   bsdconv ctl
134 */
PHP_METHOD(Bsdconv,ctl)135 PHP_METHOD(Bsdconv, ctl){
136 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
137 	struct bsdconv_instance *ins=obj->ins;
138 	zval *res=NULL;
139 	long ctl;
140 	long num;
141 	void *ptr;
142 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lrl", &ctl, &res, &num) == FAILURE){
143 		RETURN_BOOL(0);
144 	}
145 
146 	switch(ctl){
147 		case BSDCONV_CTL_ATTACH_SCORE:
148 		case BSDCONV_CTL_ATTACH_OUTPUT_FILE:
149 #if PHP_MAJOR_VERSION < 7
150 			ZEND_FETCH_RESOURCE(ptr, void *, &res, -1, "bsdconv fp", le_bsdconv_fp);
151 #else
152 			ptr = zend_fetch_resource(Z_RES_P(res), "bsdconv fp", le_bsdconv_fp);
153 #endif
154 			if(ptr==NULL){
155 				RETURN_BOOL(0);
156 			}
157 			break;
158 	}
159 
160 	bsdconv_ctl(ins, ctl, ptr, num);
161 }
162 /* }}} */
163 
164 /* {{{ proto mixed conv(string str)
165   bsdconv main function
166 */
PHP_METHOD(Bsdconv,conv)167 PHP_METHOD(Bsdconv, conv){
168 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
169 	struct bsdconv_instance *ins=obj->ins;
170 	char *c;
171 	str_size_t l;
172 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &c, &l) == FAILURE){
173 		RETURN_BOOL(0);
174 	}
175 
176 	if(ins==NULL){
177 		RETURN_BOOL(0);
178 	}
179 	bsdconv_init(ins);
180 	ins->output_mode=BSDCONV_PREMALLOCED;
181 	ins->input.data=c;
182 	ins->input.len=l;
183 	ins->input.flags=0;
184 	ins->input.next=NULL;
185 	ins->output.data=NULL;
186 	ins->flush=1;
187 	bsdconv(ins);
188 
189 #if PHP_MAJOR_VERSION < 7
190 	ins->output.data=emalloc(ins->output.len);
191 	bsdconv(ins);
192 
193 	RETURN_STRINGL(ins->output.data, ins->output.len, 0);
194 #else
195 	zend_string *ret = zend_string_alloc(ins->output.len, 0);
196 	ins->output.data=ret->val;
197 	bsdconv(ins);
198 
199 	RETURN_STR(ret);
200 #endif
201 }
202 /* }}} */
203 
204 /* {{{ proto mixed conv_chunk(string str)
205   bsdconv converting function without initializing and flushing
206 */
PHP_METHOD(Bsdconv,conv_chunk)207 PHP_METHOD(Bsdconv, conv_chunk){
208 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
209 	struct bsdconv_instance *ins=obj->ins;
210 	char *c;
211 	str_size_t l;
212 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &c, &l) == FAILURE){
213 		RETURN_BOOL(0);
214 	}
215 
216 	if(ins==NULL){
217 		RETURN_BOOL(0);
218 	}
219 	ins->output_mode=BSDCONV_PREMALLOCED;
220 	ins->input.data=c;
221 	ins->input.len=l;
222 	ins->input.flags=0;
223 	ins->input.next=NULL;
224 	ins->output.data=NULL;
225 	bsdconv(ins);
226 
227 #if PHP_MAJOR_VERSION < 7
228 	ins->output.data=emalloc(ins->output.len);
229 	bsdconv(ins);
230 
231 	RETURN_STRINGL(ins->output.data, ins->output.len, 0);
232 #else
233 	zend_string *ret = zend_string_alloc(ins->output.len, 0);
234 	ins->output.data=ret->val;
235 	bsdconv(ins);
236 
237 	RETURN_STR(ret);
238 #endif
239 }
240 /* }}} */
241 
242 /* {{{ proto mixed conv_chunk_last(string str)
243   bsdconv converting function without initializing
244 */
PHP_METHOD(Bsdconv,conv_chunk_last)245 PHP_METHOD(Bsdconv, conv_chunk_last){
246 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
247 	struct bsdconv_instance *ins=obj->ins;
248 	char *c;
249 	str_size_t l;
250 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &c, &l) == FAILURE){
251 		RETURN_BOOL(0);
252 	}
253 
254 	if(ins==NULL){
255 		RETURN_BOOL(0);
256 	}
257 	ins->output_mode=BSDCONV_PREMALLOCED;
258 	ins->input.data=c;
259 	ins->input.len=l;
260 	ins->input.flags=0;
261 	ins->input.next=NULL;
262 	ins->output.data=NULL;
263 	ins->flush=1;
264 	bsdconv(ins);
265 
266 #if PHP_MAJOR_VERSION < 7
267 	ins->output.data=emalloc(ins->output.len);
268 	bsdconv(ins);
269 
270 	RETURN_STRINGL(ins->output.data, ins->output.len, 0);
271 #else
272 	zend_string *ret = zend_string_alloc(ins->output.len, 0);
273 	ins->output.data=ret->val;
274 	bsdconv(ins);
275 
276 	RETURN_STR(ret);
277 #endif
278 }
279 /* }}} */
280 
281 /* {{{ proto mixed conv_file(string infile, string outfile)
282   bsdconv_file function
283 */
PHP_METHOD(Bsdconv,conv_file)284 PHP_METHOD(Bsdconv, conv_file){
285 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
286 	struct bsdconv_instance *ins=obj->ins;
287 	char *s1, *s2;
288 	str_size_t l,l2;
289 	FILE *inf, *otf;
290 	char *in;
291 	char *tmp;
292 	int fd;
293 
294 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &l, &s2, &l2) == FAILURE){
295 		RETURN_BOOL(0);
296 	}
297 
298 	if(ins==NULL){
299 		RETURN_BOOL(0);
300 	}
301 
302 	inf=fopen(s1,"r");
303 	if(!inf) RETURN_BOOL(0);
304 	tmp=malloc(l2+8);
305 	strcpy(tmp, s2);
306 	strcat(tmp, ".XXXXXX");
307 	if((fd=mkstemp(tmp))==-1){
308 		free(tmp);
309 		RETURN_BOOL(0);
310 	}
311 	otf=fdopen(fd,"w");
312 	if(!otf){
313 		free(tmp);
314 		RETURN_BOOL(0);
315 	}
316 
317 #ifndef WIN32
318 	struct stat stat;
319 	fstat(fileno(inf), &stat);
320 	fchown(fileno(otf), stat.st_uid, stat.st_gid);
321 	fchmod(fileno(otf), stat.st_mode);
322 #endif
323 
324 	bsdconv_init(ins);
325 	do{
326 		in=bsdconv_malloc(IBUFLEN);
327 		ins->input.data=in;
328 		ins->input.len=fread(in, 1, IBUFLEN, inf);
329 		ins->input.flags|=F_FREE;
330 		ins->input.next=NULL;
331 		if(ins->input.len==0){
332 			ins->flush=1;
333 		}
334 		ins->output_mode=BSDCONV_FILE;
335 		ins->output.data=otf;
336 		bsdconv(ins);
337 	}while(ins->flush==0);
338 
339 	fclose(inf);
340 	fclose(otf);
341 	unlink(s2);
342 	rename(tmp,s2);
343 	free(tmp);
344 
345 	RETURN_BOOL(1);
346 }
347 /* }}} */
348 
349 /* {{{ proto mixed counter([counter])
350   get counter(s) value
351 */
PHP_METHOD(Bsdconv,counter)352 PHP_METHOD(Bsdconv, counter){
353 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
354 	struct bsdconv_instance *ins=obj->ins;
355 	char *key=NULL;
356 	str_size_t l;
357 
358 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &key, &l) == FAILURE){
359 		RETURN_BOOL(0);
360 	}
361 
362 	if(key){
363 		bsdconv_counter_t *v=bsdconv_counter(ins, key);
364 		RETURN_LONG((long)(*v));
365 	}else{
366 		array_init(return_value);
367 		struct bsdconv_counter_entry *p=ins->counter;
368 		while(p){
369 			add_assoc_long(return_value, p->key, (long)(p->val));
370 			p=p->next;
371 		}
372 	}
373 }
374 /* }}} */
375 
376 /* {{{ proto void counter_reset()
377   reset all counters
378 */
PHP_METHOD(Bsdconv,counter_reset)379 PHP_METHOD(Bsdconv, counter_reset){
380 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
381 	struct bsdconv_instance *ins=obj->ins;
382 	char *key=NULL;
383 	str_size_t l;
384 
385 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &key, &l) == FAILURE){
386 		RETURN_BOOL(0);
387 	}
388 
389 	bsdconv_counter_reset(ins, key);
390 }
391 /* }}} */
392 
393 /* {{{ proto array __toString()
394   bsdconv conversion
395 */
PHP_METHOD(Bsdconv,__toString)396 PHP_METHOD(Bsdconv, __toString){
397 #define TEMPLATE "Bsdconv(\"%s\")"
398 	struct bsdconv_object *obj=(struct bsdconv_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
399 	struct bsdconv_instance *ins=obj->ins;
400 	char *s;
401 	int len=sizeof(TEMPLATE);
402 	s=bsdconv_pack(ins);
403 	len+=strlen(s);
404 
405 #if PHP_MAJOR_VERSION < 7
406 	char *s2;
407 	s2=malloc(len);
408 	sprintf(s2, TEMPLATE, s);
409 	bsdconv_free(s);
410 	RETVAL_STRING(s2, 1);
411 	free(s2);
412 #else
413 	zend_string *ret = zend_string_alloc(len, 0);
414 	sprintf(ret->val, TEMPLATE, s);
415 	bsdconv_free(s);
416 	RETURN_STR(ret);
417 #endif
418 }
419 /* }}} */
420 
421 /* {{{ proto int bsdconv_insert_phase(string conversion, string codecs, int phase_type, int phasen)
422   alter bsdconv instance */
PHP_FUNCTION(bsdconv_insert_phase)423 PHP_FUNCTION(bsdconv_insert_phase){
424 	char *conv;
425 	char *c;
426 	str_size_t l;
427 	long phase_type;
428 	long phasen;
429 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssll", &conv, &l, &c, &l, &phase_type, &phasen) == FAILURE){
430 		RETURN_LONG(-1);
431 	}
432 	char *r=bsdconv_insert_phase(conv, c, phase_type, phasen);
433 	_COMPAT_RETVAL_STRINGL(r);
434 	bsdconv_free(r);
435 }
436 /* }}} */
437 
438 /* {{{ proto int bsdconv_insert_codec(string conversion, string codec, int phasen, int codecn)
439   alter bsdconv instance */
PHP_FUNCTION(bsdconv_insert_codec)440 PHP_FUNCTION(bsdconv_insert_codec){
441 	char *conv;
442 	char *c;
443 	str_size_t l;
444 	long phasen;
445 	long codecn;
446 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssll", &conv, &l, &c, &l, &phasen, &codecn) == FAILURE){
447 		RETURN_LONG(-1);
448 	}
449 	char *r=bsdconv_insert_codec(conv, c, phasen, codecn);
450 	_COMPAT_RETVAL_STRINGL(r);
451 	bsdconv_free(r);
452 }
453 /* }}} */
454 
455 /* {{{ proto int bsdconv_replace_phase(string conversion, string codecs, int phase_type, int phasen)
456   alter bsdconv instance */
PHP_FUNCTION(bsdconv_replace_phase)457 PHP_FUNCTION(bsdconv_replace_phase){
458 	char *conv;
459 	char *c;
460 	str_size_t l;
461 	long phase_type;
462 	long phasen;
463 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssll", &conv, &l, &c, &l, &phase_type, &phasen) == FAILURE){
464 		RETURN_LONG(-1);
465 	}
466 	char *r=bsdconv_replace_phase(conv, c, phase_type, phasen);
467 	_COMPAT_RETVAL_STRINGL(r);
468 	bsdconv_free(r);
469 }
470 /* }}} */
471 
472 /* {{{ proto int bsdconv_replace_codec(string conversion, string codec, int phasen, int codecn)
473   alter bsdconv instance */
PHP_FUNCTION(bsdconv_replace_codec)474 PHP_FUNCTION(bsdconv_replace_codec){
475 	char *conv;
476 	char *c;
477 	str_size_t l;
478 	long phasen;
479 	long codecn;
480 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssll", &conv, &l, &c, &l, &phasen, &codecn) == FAILURE){
481 		RETURN_LONG(-1);
482 	}
483 	char *r=bsdconv_replace_codec(conv, c, phasen, codecn);
484 	_COMPAT_RETVAL_STRINGL(r);
485 	bsdconv_free(r);
486 }
487 /* }}} */
488 
489 /* {{{ proto string bsdconv_error(void)
490   bsdconv error message
491 */
PHP_FUNCTION(bsdconv_error)492 PHP_FUNCTION(bsdconv_error){
493 	char *c;
494 	c=bsdconv_error();
495 	_COMPAT_RETVAL_STRINGL(c);
496 	bsdconv_free(c);
497 }
498 /* }}} */
499 
500 /* {{{ proto array bsdconv_modules_list(integer)
501   list codecs
502 */
PHP_FUNCTION(bsdconv_modules_list)503 PHP_FUNCTION(bsdconv_modules_list){
504 	array_init(return_value);
505 	char **list;
506 	char **p;
507 	long phase_type;
508 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &phase_type) == FAILURE){
509 		RETURN_BOOL(0);
510 	}
511 
512 	list=bsdconv_modules_list(phase_type);
513 	p=list;
514 	while(*p!=NULL){
515 #if PHP_MAJOR_VERSION < 7
516 		add_next_index_string(return_value, *p, 1);
517 #else
518 		add_next_index_string(return_value, *p);
519 #endif
520 		bsdconv_free(*p);
521 		p+=1;
522 	}
523 	bsdconv_free(list);
524 }
525 /* }}} */
526 
PHP_FUNCTION(bsdconv_codecs_list)527 PHP_FUNCTION(bsdconv_codecs_list){
528 	array_init(return_value);
529 	char **list;
530 	char **p;
531 	long phase_type;
532 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &phase_type) == FAILURE){
533 		RETURN_BOOL(0);
534 	}
535 
536 	list=bsdconv_modules_list(phase_type);
537 	p=list;
538 	while(*p!=NULL){
539 #if PHP_MAJOR_VERSION < 7
540 		add_next_index_string(return_value, *p, 1);
541 #else
542 		add_next_index_string(return_value, *p);
543 #endif
544 		bsdconv_free(*p);
545 		p+=1;
546 	}
547 	bsdconv_free(list);
548 }
549 
550 /* {{{ proto bool bsdconv_module_check(int type, string codec)
551   check if a codec is available
552 */
PHP_FUNCTION(bsdconv_module_check)553 PHP_FUNCTION(bsdconv_module_check){
554 	char *c;
555 	str_size_t l;
556 	long phase_type;
557 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &phase_type, &c, &l) == FAILURE){
558 		RETURN_LONG(-1);
559 	}
560 	if(bsdconv_module_check(phase_type, c)){
561 		RETURN_BOOL(1);
562 	}
563 	RETURN_BOOL(0);
564 }
565 /* }}} */
566 
PHP_FUNCTION(bsdconv_codec_check)567 PHP_FUNCTION(bsdconv_codec_check){
568 	char *c;
569 	str_size_t l;
570 	long phase_type;
571 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &phase_type, &c, &l) == FAILURE){
572 		RETURN_LONG(-1);
573 	}
574 	if(bsdconv_module_check(phase_type, c)){
575 		RETURN_BOOL(1);
576 	}
577 	RETURN_BOOL(0);
578 }
579 
580 /* {{{ proto resource bsdconv_fopen(string path, string mode)
581   fopen
582 */
PHP_FUNCTION(bsdconv_fopen)583 PHP_FUNCTION(bsdconv_fopen){
584 	char *pc, *mc;
585 	str_size_t pl, ml;
586 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &pc, &pl, &mc, &ml) == FAILURE){
587 		RETURN_LONG(-1);
588 	}
589 	FILE *r=fopen(pc, mc);
590 	if(r==NULL) RETURN_BOOL(0);
591 #if PHP_MAJOR_VERSION < 7
592 	ZEND_REGISTER_RESOURCE(return_value, r, le_bsdconv_fp);
593 #else
594 	RETURN_RES(zend_register_resource(r, le_bsdconv_fp));
595 #endif
596 }
597 /* }}} */
598 
599 /* {{{ proto bool bsdconv_fclose(resource fp)
600   fclose
601 */
PHP_FUNCTION(bsdconv_fclose)602 PHP_FUNCTION(bsdconv_fclose){
603 	zval *p=NULL;
604 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &p) == FAILURE){
605 		RETURN_BOOL(0);
606 	}
607 #if PHP_MAJOR_VERSION < 7
608 	if(zend_list_delete(Z_RESVAL_P(p)) == FAILURE){
609 #else
610 	if(zend_list_delete(Z_RES_P(p)) == FAILURE){
611 #endif
612 		RETURN_BOOL(0);
613 	}
614 	RETURN_BOOL(1);
615 }
616 /* }}} */
617 
618 /* {{{ proto array(fp, path) bsdconv_mktemp(string template)
619   mkstemp
620 */
621 PHP_FUNCTION(bsdconv_mktemp){
622 	char *c;
623 	str_size_t l;
624 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &c, &l) == FAILURE){
625 		RETURN_LONG(-1);
626 	}
627 	char *t=strdup(c);
628 	int fd=bsdconv_mkstemp(t);
629 	if(fd==-1) RETURN_BOOL(0);
630 	FILE *r=fdopen(fd, "wb+");
631 	if(r==NULL) RETURN_BOOL(0);
632 	array_init(return_value);
633 
634 #if PHP_MAJOR_VERSION < 7
635 	zval *res;
636 	MAKE_STD_ZVAL(res);
637 	ZEND_REGISTER_RESOURCE(res, r, le_bsdconv_fp);
638 	add_next_index_resource(return_value, Z_RESVAL_P(res));
639 	add_next_index_string(return_value, t, 1);
640 #else
641 	zend_resource *res;
642 	res = zend_register_resource(r, le_bsdconv_fp);
643 	add_next_index_resource(return_value, res);
644 	add_next_index_string(return_value, t);
645 #endif
646 	free(t);
647 }
648 /* }}} */
649 
650 zend_function_entry bsdconv_methods[] = {
651 	PHP_ME(Bsdconv,  __construct,	arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
652 	PHP_ME(Bsdconv,  __destruct,	arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR)
653 	PHP_ME(Bsdconv,  __toString,	arginfo_void, ZEND_ACC_PUBLIC)
654 	PHP_ME(Bsdconv, conv,		arginfo_void, ZEND_ACC_PUBLIC)
655 	PHP_ME(Bsdconv, init,		arginfo_void, ZEND_ACC_PUBLIC)
656 	PHP_ME(Bsdconv, ctl,		arginfo_void, ZEND_ACC_PUBLIC)
657 	PHP_ME(Bsdconv, conv_chunk,	arginfo_void, ZEND_ACC_PUBLIC)
658 	PHP_ME(Bsdconv, conv_chunk_last,arginfo_void, ZEND_ACC_PUBLIC)
659 	PHP_ME(Bsdconv, conv_file,	arginfo_void, ZEND_ACC_PUBLIC)
660 	PHP_ME(Bsdconv, counter,	arginfo_void, ZEND_ACC_PUBLIC)
661 	PHP_ME(Bsdconv, counter_reset,	arginfo_void, ZEND_ACC_PUBLIC)
662 	{NULL, NULL, NULL}
663 };
664 
665 /* {{{ bsdconv_functions[]
666  *
667  * Every user visible function must have an entry in bsdconv_functions[].
668  */
669 zend_function_entry bsdconv_functions[] = {
670 	PHP_FE(bsdconv_insert_phase,	arginfo_void)
671 	PHP_FE(bsdconv_insert_codec,	arginfo_void)
672 	PHP_FE(bsdconv_replace_phase,	arginfo_void)
673 	PHP_FE(bsdconv_replace_codec,	arginfo_void)
674 	PHP_FE(bsdconv_error,		arginfo_void)
675 	PHP_FE(bsdconv_codecs_list,	arginfo_void)
676 	PHP_FE(bsdconv_codec_check,	arginfo_void)
677 	PHP_FE(bsdconv_modules_list,	arginfo_void)
678 	PHP_FE(bsdconv_module_check,	arginfo_void)
679 	PHP_FE(bsdconv_fopen,		arginfo_void)
680 	PHP_FE(bsdconv_fclose,		arginfo_void)
681 	PHP_FE(bsdconv_mktemp,		arginfo_void)
682 	{NULL, NULL, NULL}	/* Must be the last line in bsdconv_functions[] */
683 };
684 /* }}} */
685 
686 /* {{{ bsdconv_module_entry
687  */
688 zend_module_entry bsdconv_module_entry = {
689 	STANDARD_MODULE_HEADER,
690 	"bsdconv",
691 	bsdconv_functions,
692 	PHP_MINIT(bsdconv),
693 	PHP_MSHUTDOWN(bsdconv),
694 	NULL,
695 	NULL,
696 	PHP_MINFO(bsdconv),
697 	"11.3.0", /* Replace with version number for your extension */
698 	STANDARD_MODULE_PROPERTIES
699 };
700 /* }}} */
701 
702 #if PHP_MAJOR_VERSION < 7
703 void bsdconv_free_storage(void *object TSRMLS_DC)
704 #else
705 void bsdconv_free_storage(zend_object *object TSRMLS_DC)
706 #endif
707 {
708 	efree(object);
709 }
710 
711 #if PHP_MAJOR_VERSION < 7
712 zend_object_value bsdconv_create_handler(zend_class_entry *type TSRMLS_DC)
713 {
714 	zval *tmp;
715 	zend_object_value retval;
716 
717 	struct bsdconv_object *obj = (struct bsdconv_object *)emalloc(sizeof(struct bsdconv_object));
718 	memset(obj, 0, sizeof(struct bsdconv_object));
719 	obj->std.ce = type;
720 
721 
722 	retval.handle = zend_objects_store_put(obj, NULL, bsdconv_free_storage, NULL TSRMLS_CC);
723 	retval.handlers = &bsdconv_object_handlers;
724 
725 	return retval;
726 }
727 #else
728 zend_object * bsdconv_create_handler(zend_class_entry *type TSRMLS_DC)
729 {
730 	struct bsdconv_object *intern = ecalloc(1, sizeof(struct bsdconv_object) + zend_object_properties_size(type));
731 	zend_object_std_init(&intern->std, type TSRMLS_CC);
732 	object_properties_init(&intern->std, type TSRMLS_CC);
733 	bsdconv_object_handlers.offset = XtOffsetOf(struct bsdconv_object, std);
734 	bsdconv_object_handlers.free_obj = bsdconv_free_storage;
735 
736 	intern->std.handlers = &bsdconv_object_handlers;
737 
738 	return &intern->std;
739 }
740 #endif
741 
742 #ifdef COMPILE_DL_BSDCONV
743 ZEND_GET_MODULE(bsdconv)
744 #endif
745 
746 /* {{{ PHP_MINIT_FUNCTION
747  */
748 PHP_MINIT_FUNCTION(bsdconv)
749 {
750 	le_bsdconv_fp = zend_register_list_destructors_ex(bsdconv_fp_dtor, NULL, "bsdconv_fopen resource", module_number);
751 	zend_class_entry ce;
752 	INIT_CLASS_ENTRY(ce, "Bsdconv", bsdconv_methods);
753 	bsdconv_ce = zend_register_internal_class(&ce TSRMLS_CC);
754 	bsdconv_ce->create_object = bsdconv_create_handler;
755 	memcpy(&bsdconv_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
756 	bsdconv_object_handlers.clone_obj = NULL;
757 	REGISTER_LONG_CONSTANT("BSDCONV_FILTER", FILTER, CONST_CS|CONST_PERSISTENT);
758 	REGISTER_LONG_CONSTANT("BSDCONV_FROM", FROM, CONST_CS|CONST_PERSISTENT);
759 	REGISTER_LONG_CONSTANT("BSDCONV_INTER", INTER, CONST_CS|CONST_PERSISTENT);
760 	REGISTER_LONG_CONSTANT("BSDCONV_TO", TO, CONST_CS|CONST_PERSISTENT);
761 
762 	REGISTER_LONG_CONSTANT("BSDCONV_CTL_ATTACH_SCORE", BSDCONV_CTL_ATTACH_SCORE, CONST_CS|CONST_PERSISTENT);
763 	REGISTER_LONG_CONSTANT("BSDCONV_CTL_ATTACH_OUTPUT_FILE", BSDCONV_CTL_ATTACH_OUTPUT_FILE, CONST_CS|CONST_PERSISTENT);
764 	REGISTER_LONG_CONSTANT("BSDCONV_CTL_AMBIGUOUS_PAD", BSDCONV_CTL_AMBIGUOUS_PAD, CONST_CS|CONST_PERSISTENT);
765 	return SUCCESS;
766 }
767 /* }}} */
768 
769 /* {{{ PHP_MSHUTDOWN_FUNCTION
770  */
771 PHP_MSHUTDOWN_FUNCTION(bsdconv)
772 {
773 	return SUCCESS;
774 }
775 /* }}} */
776 
777 /* {{{ PHP_MINFO_FUNCTION
778  */
779 PHP_MINFO_FUNCTION(bsdconv)
780 {
781 	php_info_print_table_start();
782 	php_info_print_table_header(2, "bsdconv support", "enabled");
783 	php_info_print_table_end();
784 }
785 /* }}} */
786