#!/usr/bin/perl # @(#) RpSend.pl Remote-printer send program, intended to capture appsocket # (port 9100) print streams and upload them to a server from # which they can subsequently be downloaded for printing. # # Copyright (c) 2020 Graham Jenkins . All rights reserved. # This program is free software; you can redistribute it and/or modify it under # the same terms as Perl itself. Revised: 2020-05-10 use strict; # This program can be installed in /usr/local/bin and use warnings; # called through an xinetd program thus: use Getopt::Std; # service appsocket use File::Basename; # { use File::Spec; # socket_type = stream use Sys::Syslog; # protocol = tcp use LWP::UserAgent qw();# wait = no use Compress::Raw::Lzma;# user = lp use MIME::Lite; # group = sys use Sys::Hostname::Long;# server = /usr/local/bin/RpSend.pl use File::Spec; # server_args = MyPrinter@aol.com use vars qw($VERSION); # disable = no $VERSION = "1.03"; # } # It will then upload print jobs sent to port 9100 and # email a download-URL to the designated email address. use File::Temp qw/tempfile/; use Env qw/TEADATAFILE TEAUSERNAME/; # Compress subroutine; accepts string as parameter, compresses it if possible sub compress { my ($z,$o); $z=new Compress::Raw::Lzma::EasyEncoder(AppendOutput=>1,Preset=>9,Extreme=>1); if ( ($z->code($_[0],$o) ==LZMA_OK ) && ($z->flush($o,LZMA_FINISH)==LZMA_STREAM_END) ) { $_[0]=$o; return(1) } else { return(0) } } # Collect option(s), check usage my (%opts,$BadOption); $Getopt::Std::STANDARD_HELP_VERSION=1; getopts ('c',\%opts) or $BadOption="Y"; if ( defined($BadOption) || ($#ARGV != 0) || ($ARGV[0]!~m/\@/) ) { die "Usage: ".basename($0)." [-c] email-address\n". " e.g.: ".basename($0)." -c MyPrinter\@aol.com\n" } # Collect user email if possible my $user=""; if ( defined($TEAUSERNAME) ) { if ( my @p=getpwnam($TEAUSERNAME) ) { if ( open(CF,File::Spec->catdir($p[7],".RpSend.cf"))) { while ( ) {if ( ( $_=~m/\@/)&&($_!~m/^#/) ) {$user=$_;chomp($user)}} } } } # Generate sequence-number, slurp from input, then fork so that we can be # called again while compression and upload proceed my ($sec,$min,$hour) = localtime(time); my $seq=substr(100+$hour,1).substr(100+$min,1).substr(100+$sec,1); if ( defined($TEADATAFILE) ) { $seq=basename($TEADATAFILE) } syslog("info","Receiving Seq ".$seq); my $data; if ( defined($TEADATAFILE) ) { open(IN,$TEADATAFILE); $data=do { local $/; }; close(IN); fork and exit(-1) } else { $data = do { local $/; }; fork and exit } # Compress, copy to temporary file and upload compress($data) if defined ($opts{'c'}); my $size=length($data); syslog("info","Uploading Seq $seq $size bytes"); my ($fh,$tmp)=tempfile(UNLINK=>1); print $fh $data; close $fh; undef($data); my $ua = LWP::UserAgent->new(); my $response = $ua->post('https://file.io',Content_Type => 'form-data', Content => [ file => [ $tmp ], ], ); # Compose and send the message if ( $response->is_success ) { my $url=$response->decoded_content; $url=substr($url,index($url,"https://")); $url=substr($url,0,index($url,'"')); my $msg = MIME::Lite->new(From => getpwuid($<).'@'.hostname_long, To => $ARGV[0], Subject => "Remote Printer Data for Seq: $seq", Data => "Seq: $seq $size bytes =$user= $url"); $msg->send; syslog("info","Uploaded Seq $seq Link $url") } else { syslog("info","Upload Seq $seq Failed!") } __END__ =head1 NAME RpSend - Remote printing client utility =head1 README Remote-printer send program, intended to capture appsocket (port 9100) print streams and upload them to a server from which they can subsequently be downloaded for printing. =head1 DESCRIPTION C intercepts a job sent to an AppSocket printer and uploads the data file to an ephemeral file-sharing website. A link to the file location is then sent to a designated address so that the file can be downloaded and printed at a remote location. Interception is effected by an appropriate xinetd (or equivalent) service as shown in the program listing. =head1 USAGE The program can be invoked as follows: =over 5 RpSend [-c] email-address =back e.g. RpSend MyPrinter@aol.com If the [-c] option is used, the data stream will be compressed before transmission. C can be called using the Tea4CUPS package by appending to its configuration file lines like: prehook_spool : /usr/local/bin/RpSend MyPrinter@aol.com keepfiles : no If C is called via Tea4CUPS, it will attempt to read the sender's email address from a file called C<.RpSend.cf> in his home directory. C always forks the compression and transmission operations so that it may be called repeatedly without significant delays. =head1 SCRIPT CATEGORIES Networking UNIX/System_administration =head1 AUTHOR Graham Jenkins =head1 COPYRIGHT Copyright (c) 2020 Graham Jenkins. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut