@@ -500,50 +500,84 @@ function convertSvgToPng(string $svg): string
500
500
$ svg = preg_replace ("/(animation: currstreak[^;' \"]+)/m " , "font-size: 28px; " , $ svg );
501
501
$ svg = preg_replace ("/<a \X*?>(\X*?)<\/a>/m " , '\1 ' , $ svg );
502
502
503
- // save svg to random file
504
- $ filename = uniqid ();
505
- file_put_contents ("$ filename.svg " , $ svg );
503
+ // escape svg for shell
504
+ $ svg = escapeshellarg ($ svg );
505
+
506
+ // `--pipe`: read input from pipe (stdin)
507
+ // `--export-filename -`: write output to stdout
508
+ // `-w 495 -h 195`: set width and height of the output image
509
+ // `--export-type png`: set the output format to PNG
510
+ $ cmd = "echo {$ svg } | inkscape --pipe --export-filename - -w 495 -h 195 --export-type png " ;
506
511
507
512
// convert svg to png
508
- $ out = shell_exec ("inkscape -w 495 -h 195 {$ filename }.svg -o {$ filename }.png " ); // skipcq: PHP-A1009
509
- if ($ out !== null ) {
510
- throw new Exception ("Error converting SVG to PNG: $ out " );
513
+ $ png = shell_exec ($ cmd ); // skipcq: PHP-A1009
514
+
515
+ // check if the conversion was successful
516
+ if (empty ($ png )) {
517
+ // `2>&1`: redirect stderr to stdout
518
+ $ error = shell_exec ("$ cmd 2>&1 " ); // skipcq: PHP-A1009
519
+ throw new Exception ("Failed to convert SVG to PNG: {$ error }" , 500 );
511
520
}
512
521
513
- // read png data and delete temporary files
514
- $ png = file_get_contents ("{$ filename }.png " );
515
- unlink ("{$ filename }.svg " );
516
- unlink ("{$ filename }.png " );
522
+ // return the generated png
517
523
return $ png ;
518
524
}
519
525
520
526
/**
521
- * Set headers and echo response based on type
527
+ * Return headers and response based on type
522
528
*
523
529
* @param string|array $output The stats (array) or error message (string) to display
530
+ *
531
+ * @return array The Content-Type header and the response body, and status code in case of an error
524
532
*/
525
- function renderOutput (string |array $ output, int $ responseCode = 200 ): void
533
+ function generateOutput (string |array $ output ): array
526
534
{
527
535
$ requestedType = $ _REQUEST ["type " ] ?? "svg " ;
528
- http_response_code ($ responseCode );
529
536
530
537
// output JSON data
531
538
if ($ requestedType === "json " ) {
532
- // set content type to JSON
533
- header ("Content-Type: application/json " );
534
539
// generate array from output
535
540
$ data = gettype ($ output ) === "string " ? ["error " => $ output ] : $ output ;
536
- // output as JSON
537
- echo json_encode ($ data );
541
+ return [
542
+ "contentType " => "application/json " ,
543
+ "body " => json_encode ($ data ),
544
+ ];
538
545
}
539
- // output SVG or PNG card
540
- else {
541
- // set content type to SVG or PNG
542
- header ("Content-Type: image/ " . ($ requestedType === "png " ? "png " : "svg+xml " ));
543
- // render SVG card
544
- $ svg = gettype ($ output ) === "string " ? generateErrorCard ($ output ) : generateCard ($ output );
545
- // output PNG if PNG is requested, otherwise output SVG
546
- echo $ requestedType === "png " ? convertSvgToPng ($ svg ) : $ svg ;
546
+ // Generate SVG card
547
+ $ svg = gettype ($ output ) === "string " ? generateErrorCard ($ output ) : generateCard ($ output );
548
+ // output PNG card
549
+ if ($ requestedType === "png " ) {
550
+ try {
551
+ $ png = convertSvgToPng ($ svg );
552
+ return [
553
+ "contentType " => "image/png " ,
554
+ "body " => $ png ,
555
+ ];
556
+ } catch (Exception $ e ) {
557
+ return [
558
+ "contentType " => "image/svg+xml " ,
559
+ "status " => 500 ,
560
+ "body " => generateErrorCard ($ e ->getMessage ()),
561
+ ];
562
+ }
547
563
}
548
- exit ();
564
+ // output SVG card
565
+ return [
566
+ "contentType " => "image/svg+xml " ,
567
+ "body " => $ svg ,
568
+ ];
569
+ }
570
+
571
+ /**
572
+ * Set headers and output response
573
+ *
574
+ * @param string|array $output The Content-Type header and the response body
575
+ * @param int $responseCode The HTTP response code to send
576
+ */
577
+ function renderOutput (string |array $ output , int $ responseCode = 200 ): void
578
+ {
579
+ $ response = generateOutput ($ output );
580
+ http_response_code ($ response ["status " ] ?? $ responseCode );
581
+ header ("Content-Type: {$ response ["contentType " ]}" );
582
+ exit ($ response ["body " ]);
549
583
}
0 commit comments