If the qrencode command is installed, use it to generate QR codes locally instead of the Google chart API https://github.com/webmin/webmin/issues/2115

This commit is contained in:
Jamie Cameron
2024-04-07 16:14:25 -07:00
parent e4aee1c27e
commit 21845e9708
3 changed files with 76 additions and 4 deletions

20
webmin/qr.cgi Executable file
View File

@ -0,0 +1,20 @@
#!/usr/local/bin/perl
# Show a QR code based on parameters
use strict;
use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
$main::no_acl_check = 1;
require './webmin-lib.pl';
our (%in, %text, %gconfig, %config);
&ReadParse();
&error_setup($text{'qr_err'});
$in{'str'} || &error($text{'qr_estr'});
my ($img, $mime) = &generate_qr_code($in{'str'}, $in{'size'});
$img || &error($mime);
&PrintHeader(undef, $mime);
print $img;

View File

@ -229,10 +229,17 @@ return undef;
sub message_twofactor_totp
{
my ($user) = @_;
my $name = &urlize(&get_display_hostname() . " (" . $user->{'name'} . ")");
my $url = "https://chart.googleapis.com/chart".
"?chs=200x200&cht=qr&chl=otpauth://totp/".
$name."%3Fsecret%3D".$user->{'twofactor_id'};
my $name = &get_display_hostname()." (".$user->{'name'}.")";
my $str = "otpauth://totp/".$name."?secret=".$user->{'twofactor_id'};
my $url;
if (&can_generate_qr()) {
$url = "$gconfig{'webprefix'}/webmin/qr.cgi?".
"size=4&str=".&urlize($str);
}
else {
$url = "https://chart.googleapis.com/chart".
"?chs=200x200&cht=qr&chl=".&urlize($str);
}
my $rv;
$rv .= &text('twofactor_qrcode', "<tt>$user->{'twofactor_id'}</tt>")."<p>\n";
$rv .= "<img src='$url' border=0><p>\n";

View File

@ -2772,4 +2772,49 @@ closedir(DIR);
return @rv;
}
# can_generate_qr()
# Returns 1 if QR codes can be generated on this system
sub can_generate_qr
{
if (&has_command("qrencode")) {
return 1;
}
eval "use Image::PNG::QRCode";
if (!$@) {
return 1;
}
return 0;
}
# generate_qr_code(string, [block-size])
# Turn a string into a QR code image, and returns the data and MIME type
sub generate_qr_code
{
my ($str, $size) = @_;
if (&has_command("qrencode")) {
# Use the qrencode shell command
my $cmd = "qrencode -o - -t PNG ".quotemeta($str);
$cmd .= " -s ".quotemeta($size) if ($size);
my ($out, $err);
my $ex = &execute_command($cmd, undef, \$out, \$err);
if ($ex) {
return (undef, $err);
}
return ($out, "image/png");
}
eval "use Image::PNG::QRCode";
if (!$@) {
# Use a Perl module
my $out;
Image::PNG::QRCode::qrpng(
text => $str,
scale => $size || 3,
out => \$out,
);
return ($out, "image/png");
}
return (undef, "QR code generation requires either the qrencode command or ".
"Image::PNG::QRCode Perl module");
}
1;