aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile146
-rw-r--r--config.def.mk15
-rwxr-xr-xgpigeon-template.cgi117
-rwxr-xr-xgpigeonctl.def.pl2
-rw-r--r--link-tmpl-template.cgi169
-rw-r--r--styles.css22
6 files changed, 311 insertions, 160 deletions
diff --git a/Makefile b/Makefile
index 1a5ed63..323e708 100644
--- a/Makefile
+++ b/Makefile
@@ -6,71 +6,50 @@ STOP=\033[0m
include config.mk
gpigeon: gpigeon-template.cgi link-tmpl-template.cgi
- @if test -z '$(BINPREFIX)'; then \
- printf "\n$(RED)No \u0024BINPREFIX variable defined in config.mk.\n";\
- printf "Look into config.def.mk for the defaults and fix that in your config.mk.$(STOP)\n";\
- exit 1;\
- else \
- printf "\n\u0024BINPREFIX var is set to $(BOLD)$(BINPREFIX)$(STOP)";\
- fi
- @if test -z '$(PREFIX)'; then \
- printf "\n$(RED)No \u0024PREFIX variable defined in config.mk.\n";\
- printf "Look into config.def.mk for the defaults and fix that in your config.mk.$(STOP)\n";\
- exit 1;\
- else \
- printf "\n\u0024PREFIX var is set to $(BOLD)$(PREFIX)$(STOP)";\
- fi
- @if test -z '$(WWWPREFIX)'; then\
- printf "\n${RED}No web directory defined in config.mk. Check your config.def.mk for the defaults and fix that in your config.mk.${STOP}";\
- exit 1; \
- else \
- printf "\nThe WWW directory is $(BOLD)$(WWWDIR)$(STOP)";\
- fi
- @if test -z '$(DB_PATH)'; then\
- printf "\n${RED}No database path defined in config.mk. Check your config.def.mk for the defaults and fix that in your config.mk$(STOP)";\
- exit 1; \
- else \
- printf "\nThe path to the SQLite database is $(BOLD)$(DB_PATH)$(STOP)";\
- sed -e 's|db_path_goes_here|$(DB_PATH)|g' gpigeon-template.cgi > gpigeon.cgi;\
- fi
-
- @if test -n '$(_GPG_HOMEDIR)'; then \
- printf "\nThe home directory for GPG will be ${BOLD}$(_GPG_HOMEDIR)${STOP}" ;\
- else \
- printf "\n${RED}The GPG home directory for gpigeon wasn't set in config.mk . Fix that.${STOP}" ;\
- $(MAKE) clean ;\
- exit 1;\
- fi
+ $(MAKE) gpigeonctl;
@if test -n '$(LINK_TEMPLATE_PATH)'; then \
printf "\nLink template is at ${BOLD}$(LINK_TEMPLATE_PATH)${STOP}\n"; \
- sed -e 's|link_template_path_goes_here|$(LINK_TEMPLATE_PATH)|g' -i gpigeon.cgi; \
else \
printf "\n${RED}The path for the link template wasn't set in your config.mk. Fix that.${STOP}" ;\
exit 1;\
fi
+ @if test -n '$(UPLOAD_TMPDIR)'; then \
+ printf "\nUploaded files will be temporary stored at ${BOLD}$(UPLOAD_TMPDIR)${STOP}"; \
+ else \
+ printf "\n${RED}The temporary directory for uploaded files wasn't set in your config.mk. Fix that.${STOP}" ;\
+ exit 1;\
+ fi
@if test -n '$(MSG_FORM_CHAR_LIMIT)'; then \
- printf "Message form will have a message limit of ${BOLD}$(MSG_FORM_CHAR_LIMIT) characters${STOP}\n"; \
- sed -e "s|msg_char_limit_goes_here|$(MSG_FORM_CHAR_LIMIT)|g" link-tmpl-template.cgi > link-tmpl.cgi;\
+ printf "\nMessage form will have a message limit of ${BOLD}$(MSG_FORM_CHAR_LIMIT) characters${STOP}\n"; \
else \
printf "${RED}No character limits were defined in your config.mk. Fix that.${STOP}\n" ;\
$(MAKE) clean ;\
exit 1;\
fi
+ @if test -n '$(MAILSENDER)'; then \
+ printf "Encrypted mails will be sent from ${BOLD}$(MAILSENDER)${STOP}\n"; \
+ else \
+ printf "${RED}No mail sender adress configured in your config.mk. Fix this.${STOP}\n" ; \
+ $(MAKE) clean ; \
+ exit 1; \
+ fi
+ @sed -e 's|bin_path_goes_here|$(BINPREFIX)|g' gpigeon-template.cgi > gpigeon.cgi;
+ @sed -e 's|db_path_goes_here|$(DB_PATH)|g' -i gpigeon.cgi;
+ @sed -e 's|link_template_path_goes_here|$(LINK_TEMPLATE_PATH)|g' -i gpigeon.cgi;
+ @sed -e 's|cookies_dir_goes_here|$(COOKIES_DIR)|g' -i gpigeon.cgi;
+ @sed -e 's|bin_path_goes_here|$(BINPREFIX)|g' link-tmpl-template.cgi > link-tmpl.cgi;
+ @sed -e "s|msg_char_limit_goes_here|$(MSG_FORM_CHAR_LIMIT)|g" -i link-tmpl.cgi;
+ @sed -e 's|has_mailserver_goes_here|$(HAS_MAILSERVER)|g' -i link-tmpl.cgi;
+ @sed -e 's|sender_addr_goes_here|$(MAILSENDER)|g' -i link-tmpl.cgi;
+ @sed -e 's|gpg_homedir_goes_here|$(_GPG_HOMEDIR)|g' -i link-tmpl.cgi;
+ @sed -e 's|tmp_dir_goes_here|$(UPLOAD_TMPDIR)|g' -i link-tmpl.cgi; \
@if [ '${HAS_MAILSERVER}' == '1' ]; then \
printf "Local mail server setup. ${BOLD}Mail::Sendmail module will be used to send the mails${STOP}.\n"; \
else \
printf "External mail server setup. ${BOLD}Net::SMTPS module will be used to send the mails${STOP}.\n"; \
- if test -n '$(MAILSENDER)'; then \
- printf "\tEncrypted mails will be sent from ${BOLD}$(MAILSENDER)${STOP}\n"; \
- sed -e 's|sender_addr_goes_here|$(MAILSENDER)|g' -i link-tmpl.cgi; \
- else \
- printf "\t${RED}No mail sender adress configured in your config.mk. Fix this.${STOP}\n" ; \
- $(MAKE) clean ; \
- exit 1; \
- fi; \
if test -n '$(MAILSENDER_PW)'; then \
printf "\tPassword for ${BOLD}${MAILSENDER}${STOP} is %s.\n" '${MAILSENDER_PW}'; \
sed -e 's|sender_pw_goes_here|$(MAILSENDER_PW)|g' -i link-tmpl.cgi; \
@@ -96,22 +75,39 @@ gpigeon: gpigeon-template.cgi link-tmpl-template.cgi
exit 1; \
fi; \
fi
-
- @sed -e 's|has_mailserver_goes_here|$(HAS_MAILSERVER)|g' -i link-tmpl.cgi;
- @sed -e 's|gpg_homedir_goes_here|$(_GPG_HOMEDIR)|g' -i link-tmpl.cgi;
@if test -n '$(WWWDOMAIN)' && test -n '$(WWWPREFIX)'; then\
$(MAKE) nginxconf;\
printf "Done generating $(WWWDOMAIN).conf for nginx.";\
fi
+
@printf "\nDone preparing files. You can now type\n\t$$ sudo make install\nin your terminal.\n"
gpigeonctl: gpigeonctl.def.pl
+ @$(MAKE) check_cookiesdir;
+ @$(MAKE) check_dbpath;
+ @$(MAKE) check_prefixes;
+ @$(MAKE) check_gpghomedir;
+ @if test -n '$(WWWUSER)'; then \
+ printf "The following UNIX user will be used for chowning and gpigeonctl: ${BOLD}$(WWWUSER)${STOP}\n"; \
+ else \
+ printf "\t${RED}No user configured. Check your config.mk${STOP}.\n"; \
+ $(MAKE) clean ; \
+ exit 1; \
+ fi
+ @if test -n '$(WWWGROUP)'; then \
+ printf "The following UNIX group will be used for chowning: ${BOLD}$(WWWGROUP)${STOP}\n"; \
+ else \
+ printf "\t${RED}No group configured. Check your config.mk${STOP}.\n"; \
+ $(MAKE) clean ; \
+ exit 1; \
+ fi
@sed -e 's|gpgdir_goes_here|$(_GPG_HOMEDIR)|g' gpigeonctl.def.pl > gpigeonctl;
@sed -e 's|cookies_dir_goes_here|$(COOKIES_DIR)|g' -i gpigeonctl ;
@sed -e 's|db_path_goes_here|$(DB_PATH)|g' -i gpigeonctl;
@sed -e 's|web_user_goes_here|$(WWWUSER)|g' -i gpigeonctl;
@sed -e 's|web_dir_goes_here|$(WWWDIR)|g' -i gpigeonctl;
- chmod +x gpigeonctl;
+ @sed -e 's|bin_path_goes_here|$(BINPREFIX)|g' -i gpigeonctl;
+ @chmod +x gpigeonctl;
install:
$(MAKE) gpigeon gpigeonctl;
@@ -127,6 +123,7 @@ install:
install -Dm600 link-tmpl.cgi $(DESTDIR)$(LINK_TEMPLATE_PATH)
install -Dm644 index.html favicon.ico styles.css -t $(DESTDIR)$(WWWDIR)/
install -Dm755 gpigeonctl -t $(DESTDIR)$(BINPREFIX)
+ chown $(WWWUSER):$(WWWGROUP) -R $(DESTDIR)$(GPIGEON_DIR)
@printf "Done. Now execute `gpigeonctl init' to initialize the database.\n"
nginxconf: nginx-example.conf
@@ -135,10 +132,57 @@ nginxconf: nginx-example.conf
uninstall:
rm -f $(DESTDIR)$(BINPREFIX)/gpigeonctl
- rm -rf $(DESTDIR)$(PREFIX)/gpigeon
+ rm -rf $(DESTDIR)$(GPIGEON_DIR)
rm -rf $(DESTDIR)$(WWWDIR)
clean:
rm -f genpass.txt gpg.txt link-tmpl.cgi gpigeon.cgi $(WWWDOMAIN).conf the.db gpigeonctl
+check_cookiesdir:
+ @if test -n '$(COOKIES_DIR)'; then \
+ printf "\nThe cookies will be stored in ${BOLD}$(COOKIES_DIR)${STOP}"; \
+ else \
+ printf "\n${RED}No cookie directory configured. Check your config.def.mk for the defaults and fix that.${STOP}" ;\
+ exit 1; \
+ fi
+
+check_dbpath:
+ @if test -z '$(DB_PATH)'; then\
+ printf "\n${RED}No database path defined in config.mk. Check your config.def.mk for the defaults and fix that in your config.mk$(STOP)";\
+ exit 1; \
+ else \
+ printf "\nThe path to the SQLite database is $(BOLD)$(DB_PATH)$(STOP)";\
+ fi
+
+check_prefixes:
+ @if test -z '$(PREFIX)'; then \
+ printf "\n$(RED)No \u0024PREFIX variable defined in config.mk.\n";\
+ printf "Look into config.def.mk for the defaults and fix that in your config.mk.$(STOP)\n";\
+ exit 1;\
+ else \
+ printf "\n\u0024PREFIX var is set to $(BOLD)$(PREFIX)$(STOP)";\
+ fi
+ @if test -z '$(BINPREFIX)'; then \
+ printf "\n$(RED)No \u0024BINPREFIX variable defined in config.mk.\n";\
+ printf "Look into config.def.mk for the defaults and fix that in your config.mk.$(STOP)\n";\
+ exit 1;\
+ else \
+ printf "\n\u0024BINPREFIX var is set to $(BOLD)$(BINPREFIX)$(STOP)";\
+ fi
+ @if test -z '$(WWWPREFIX)'; then\
+ printf "\n${RED}No web directory defined in config.mk. Check your config.def.mk for the defaults and fix that in your config.mk.${STOP}";\
+ exit 1; \
+ else \
+ printf "\nThe WWW directory is $(BOLD)$(WWWDIR)$(STOP)";\
+ fi
+
+check_gpghomedir:
+ @if test -n '$(_GPG_HOMEDIR)'; then \
+ printf "\nThe home directory for GPG will be ${BOLD}$(_GPG_HOMEDIR)${STOP}" ;\
+ else \
+ printf "\n${RED}The GPG home directory for gpigeon wasn't set in config.mk . Fix that.${STOP}" ;\
+ $(MAKE) clean ;\
+ exit 1;\
+ fi
+
.PHONY: clean install uninstall
diff --git a/config.def.mk b/config.def.mk
index 931671f..f860bf3 100644
--- a/config.def.mk
+++ b/config.def.mk
@@ -1,20 +1,23 @@
# Customize below to fit your system
# prefixes
-BINPREFIX = /usr/local/bin
PREFIX = /usr/share
+BINPREFIX = /usr/bin
WWWPREFIX = /var/www
# system stuff
WWWUSER = 'www-data'
+WWWGROUP = 'www-data'
# paths
-COOKIES_DIR = $(PREFIX)/gpigeon/cookies
-_GPG_HOMEDIR = $(PREFIX)/gpigeon/gnupg
-WWWDIR = $(WWWPREFIX)/gpigeon
-LINK_TEMPLATE_PATH = $(PREFIX)/gpigeon/link-tmpl.cgi
+GPIGEON_DIR=$(PREFIX)/gpigeon
+COOKIES_DIR = $(GPIGEON_DIR)/cookies
+UPLOAD_TMPDIR = $(GPIGEON_DIR)/tmp/
+LINK_TEMPLATE_PATH = $(GPIGEON_DIR)/link-tmpl.cgi
+DB_PATH=$(GPIGEON_DIR)/the.db
+_GPG_HOMEDIR = $(GPIGEON_DIR)/gnupg
GPIGEON_PATH = $(WWWDIR)/cgi-bin/gpigeon.cgi
-DB_PATH=$(PREFIX)/gpigeon/the.db
+WWWDIR = $(WWWPREFIX)/gpigeon
# one time gpg form tuning
MSG_FORM_CHAR_LIMIT = 3000
diff --git a/gpigeon-template.cgi b/gpigeon-template.cgi
index 646846d..7757bcb 100755
--- a/gpigeon-template.cgi
+++ b/gpigeon-template.cgi
@@ -27,6 +27,8 @@ use CGI::Cookie;
use CGI::Carp qw(fatalsToBrowser);
use File::Path qw(mkpath rmtree);
+delete @ENV{qw(IFS PATH CDPATH BASH_ENV)};
+$ENV{'PATH'} = q{bin_path_goes_here};
my $rIP = $ENV{REMOTE_ADDR};
my $uagent = $ENV{HTTP_USER_AGENT};
@@ -173,7 +175,7 @@ sub LoginCookieGen {
-samesite => 'Strict',
) or die "Can't create cookie $!";
open my $out, '>', $cookiefile or die "Can't write to $cookiefile: $!";
- print $out "$rIP\n$ua\n$new_magic_cookie\n$new_userid_cookie";
+ print $out "$rIP\n$uagent\n$new_magic_cookie\n$new_userid_cookie";
close $out;
print "Set-Cookie: $new_magic_cookie\n";
print "Set-Cookie: $new_userid_cookie\n";
@@ -192,22 +194,9 @@ sub UntaintCGIFilename {
return $filename;
}
-sub NotifIfDefined{
- my $notif = shift;
- if (defined $notif){
- return $notif;
- }
- else{
- return '<!--undef notif-->';
- }
-}
-
-delete @ENV{qw(IFS PATH CDPATH BASH_ENV)};
-$ENV{'PATH'} = '/usr/bin';
my $hostname = $ENV{'SERVER_NAME'};
my $db_path = q{db_path_goes_here};
-my $argon2id_hash = q{argon2id_hash_goes_here};
my $cookiesdir = q{cookies_dir_goes_here};
my $link_template_path = q{link_template_path_goes_here};
@@ -216,37 +205,40 @@ my %text_strings = (
addr_ok => 'is valid!',
addr_nok => 'is not valid !',
addr_unknown => 'Unknown',
- create_link_btn => 'Generate link',
+ create_link_btn => 'Generate link',
+ cookie_problems =>'You got a cookie problem.<br> <b>Clean them and log in again</b>',
delete_link_btn_text => 'Delete',
delete_links_btn_text => 'Delete all links',
disconnect_btn_text => 'Disconnect',
logout_btn_text => 'Logout',
here => 'here',
+ loginbtn => 'Log in',
link_asker_field_label => "Asker's mail :",
- link_web_title => 'One time GPG messaging form',
link_del_ok => 'Successful removal !',
link_legend_textarea =>'Type your message below :',
- link_send_btn => 'Send',
link_ok_for => 'Generated a link for',
link_del_failed => 'Deletion failed and here is why : ',
link_generated_ok => "Here's the link",
mailto_body => 'Your link is ',
mailto_subject => 'Link to your one time GPG messaging form',
- notif_login_failure => 'Cannot login. Check if your username and password match.',
+ incorrect_ids => 'Username/password combination<br> is incorrect.<br>Try again.',
+ password_label => 'Password',
+ refresh_btn => 'Refresh',
theader_link => 'Link',
theader_for => 'For',
- theader_deletion => 'Deletion',
+ theader_deletion => 'Deletion',
+ username_label => 'Username',
web_title => 'GPIGEON.CGI: generate one time GPG messaging links !',
- web_greet_msg => 'Hi and welcome.',
+ web_greet_msg => 'Hi and welcome. What will you do today ?',
);
my $cgi_query_get = CGI->new;
my $username = $cgi_query_get->param('username');
my $pass = $cgi_query_get->param('password');
my $disconnect = $cgi_query_get->param('disconnect');
-my ($linkgen_notif, $mailisok_notif, $deletion_notif, $checkedornot,
- $session, $hidden_loginfield, $magic_cookie,
+my ( $checkedornot, $hidden_loginfield, $magic_cookie,
$uid_cookie, $idval, $refresh_form, $userid) = undef;
+my $linkgen_notif = my $mailisok_notif = my $deletion_notif = my $login_notif = '<!-- undef notif -->';
my @created_links = ();
my %cur_cookies = CGI::Cookie->fetch;
$uid_cookie = $cur_cookies{'uid'};
@@ -259,12 +251,12 @@ if (not defined $magic_cookie){ # cookie is not set
$refresh_form = qq{<form method="POST">
$hidden_loginfield
- <input id="refreshbtn" type="submit" value="$text_strings{refresh_btn_text}">
+ <input id="refreshbtn" type="submit" value="$text_strings{refresh_btn}">
</form>};
}else{
$hidden_loginfield = qq{<!-- undef -->};
$refresh_form = qq{<form method="GET">
- <input id="refreshbtn" type="submit" value="$text_strings{refresh_btn_text}">
+ <input id="refreshbtn" type="submit" value="$text_strings{refresh_btn}">
</form>};
$idval = $magic_cookie->value;
if ($idval =~ /^([\w]+)$/){
@@ -319,7 +311,6 @@ if($loginok){
$userid = $loginok;
LoginCookieGen($userid, $magic_cookie, $cookiesdir);
my $user_mailaddr = DbGetLine($dbh, qq{SELECT mail from pigeons where userid='$userid';});
- my $gpgid = DbGetLine($dbh, qq{SELECT gpgfp from pigeons where userid='$userid';});
my $nick = DbGetLine($dbh, qq{SELECT name from pigeons where userid='$userid';});
if (not -d "./l/$userid"){
mkpath("./l/$userid");
@@ -356,14 +347,7 @@ if($loginok){
open my $out, '>', $LINK_PATH or die "Can't write to link file: $!";
while( <$in> ) {
s/{link_user}/{$link_asker}/g;
- s/{gpgid_goes_here}/{$gpgid}/g;
- s/{link_filename}/{$GENERATED_FORM_FILENAME}/g;
- s/{user_mailaddr_goes_here}/{$user_mailaddr}/g;
- s/{msg_too_long}/$text_strings{msg_too_long}/g;
- s/{msg_empty}/$text_strings{msg_empty}/g;
- s/{link_web_title}/$text_strings{link_web_title}/g;
- s/{link_send_btn}/$text_strings{link_send_btn}/g;
- s/{type_msg_below}/$text_strings{type_msg_below}/g;
+ s/{user_mailaddr_goes_here}/{$user_mailaddr}/g;
print $out $_;
}
close $in or die;
@@ -427,7 +411,7 @@ if($loginok){
<title>$text_strings{web_title}</title>
</head>
<body>
- <p>$text_strings{web_greet_msg} <b>$nick</b></p>
+ <p>$text_strings{web_greet_msg}</p>
<form method="GET">
<input type="hidden" name="disconnect" value="1">
<input id="logoutbtn" type="submit" value="$text_strings{disconnect_btn_text}">
@@ -438,20 +422,20 @@ if($loginok){
<form method="POST">
$hidden_loginfield
Mail de la personne:<br>
- <input id="mailfied" tabindex="1" type="text" name="mail">
+ <input id="mailfield" tabindex="1" type="text" name="mail">
<input id="genlinkbtn" tabindex="2" type="submit" value="$text_strings{create_link_btn}">
- </form>},
- NotifIfDefined($mailisok_notif),
- '<br>',
- NotifIfDefined($linkgen_notif),
- qq{<hr>
+ </form>
+ $mailisok_notif
+ <br>
+ $linkgen_notif
+ <hr>
<form method="POST">
$hidden_loginfield
<input type="hidden" name="supprtout">
<input id="deleteallbtn" type="submit" value="$text_strings{delete_links_btn_text}">
- </form>},
- NotifIfDefined($deletion_notif),
- qq{<table>
+ </form>
+ $deletion_notif
+ <table>
<tr>
<th>$text_strings{theader_link} &#128279;</th>
<th>$text_strings{theader_for} &#128231;</th>
@@ -464,5 +448,50 @@ if($loginok){
}
else{
$dbh->disconnect;
- print "Location: /\n\n";
+ if (not $disconnect and defined $magic_cookie){
+ $login_notif = qq{<span id="failure">$text_strings{cookie_problems}</span>};
+ }
+ if (length($pass) > 0 or length($username) > 0){
+ $login_notif = qq{<span id="failure">$text_strings{incorrect_ids}</span>};
+ }
+
+ print "Content-type: text/html\n\n",
+qq{<!DOCTYPE html>
+<html lang="fr">
+<head>
+<meta charset="utf-8">
+<link rel="icon" type="image/x-icon" href="/favicon.ico">
+<link rel="stylesheet" type="text/css" href="/styles.css">
+<title>$text_strings{landingpage_title}</title>
+</head>
+<body>
+<h1>$text_strings{landingpage_title}</h1>
+<form action="/cgi-bin/gpigeon.cgi" method="POST">
+<table id="loginbox">
+<tbody>
+ <tr>
+ <td>$text_strings{username_label} :</td>
+ <td><input type="password" name="password"></td>
+ </tr>
+ <tr>
+ <td>$text_strings{password_label} :</td>
+ <td><input type="password" name="password"></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td id="loginerr">$login_notif</td>
+ </tr>
+ <tr id="authbtn">
+ <td></td>
+ <td><input type="submit" value="$text_strings{loginbtn}"></td>
+ </tr>
+</tbody>
+</table>
+</form>
+
+<p><a href="http://git.les-miquelots.net/gpigeon"
+ title="gpigeon download link">Source code here.</a> It is similar to <a h>
+
+</body>
+</html>};
}
diff --git a/gpigeonctl.def.pl b/gpigeonctl.def.pl
index 4585967..b7d4108 100755
--- a/gpigeonctl.def.pl
+++ b/gpigeonctl.def.pl
@@ -23,7 +23,7 @@ use Term::ReadKey;
use Crypt::Argon2 qw(argon2id_pass);
use DBI;
delete @ENV{qw(IFS PATH CDPATH BASH_ENV)};
-$ENV{'PATH'} = '/usr/bin';
+$ENV{'PATH'} = q{bin_path_goes_here};
my $dbh_path = q{db_path_goes_here};
my $cookiesdir = q{cookies_dir_goes_here};
my $GNUPGHOME = q{gpgdir_goes_here};
diff --git a/link-tmpl-template.cgi b/link-tmpl-template.cgi
index 5ac8dd4..3189b8f 100644
--- a/link-tmpl-template.cgi
+++ b/link-tmpl-template.cgi
@@ -1,24 +1,43 @@
-#! /usr/bin/perl -wT
+#! /usr/bin/perl -T
+# link-tmpl.cgi : self-destructing message form to send yourself GPG
+# encrypted messages. Part of gpigeon.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Copyright (c) 2020-2021, Miquel Lionel <lionel@les-miquelots.net>
my $linkuser = q{link_user};
-my $linkfilename = q{link_filename};
use warnings;
use strict;
-use GPG;
use CGI qw(param);
-$ENV{'PATH'}="/usr/bin";
delete @ENV{qw(IFS PATH CDPATH BASH_ENV)};
+$ENV{'PATH'}=q{bin_path_goes_here};
+$ENV{TMPDIR}=q{tmp_dir_goes_here};
+
+sub GetRFC822Date {
+ # https://stackoverflow.com/a/40149475, Daniel VÃritÃ
+ use POSIX qw(strftime locale_h);
+ my $old_locale = setlocale(LC_TIME, "C");
+ my $date = strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time()));
+ setlocale(LC_TIME, $old_locale);
-sub EscapeArobase {
- my $escapedmailaddress = shift;
- $escapedmailaddress =~ s/@/\\@/;
- return $escapedmailaddress;
+ return $date;
}
my $HAS_MAILSERVER = q{has_mailserver_goes_here};
my $msg_form_char_limit = q{msg_char_limit_goes_here};
-my $mymailaddr = q{user_mailaddr_goes_here};
-my $mymail_gpgid = q{gpgid_goes_here}; #0xlong keyid form
+my $mailaddr = q{user_mailaddr_goes_here};
my $mailsender = q{sender_addr_goes_here};
my $mailsender_smtp = q{smtp_domain_goes_here};
my $mailsender_port = q{smtp_port_goes_here};
@@ -27,77 +46,113 @@ my $GPG_HOMEDIR = q{gpg_homedir_goes_here};
my $cgi_query_get = CGI->new;
my $msg_form = $cgi_query_get->param('msg');
my $length_msg_form = length $msg_form;
-my ($enc_msg, $error_processing_msg) = undef;
+my ($smtp, $enc_msg) = undef;
+my $form_error_notif = '<!-- undef notif -->';
+my $max_mb = 100;
+$CGI::POST_MAX = 1024*1024*$max_mb; # 100MBytes
+my $fupload_limit = $CGI::POST_MAX;
if (defined $length_msg_form and $length_msg_form > $msg_form_char_limit){
- $error_processing_msg = qq{<span id="failure"><b>Cannot send message : message length must be under $msg_form_char_limit characters.</b></span>};
+ $form_error_notif = qq{<span id="failure"><b>Cannot send message : message length must be under $msg_form_char_limit characters.</b></span>};
}
elsif (defined $length_msg_form and $length_msg_form eq 0 ){
- $error_processing_msg = qq{<span id="failure"><b>Cannot send message : message is empty. You can type up to $msg_form_char_limit characters.</b></span>};
+ $form_error_notif = qq{<span id="failure"><b>Cannot send message : message is empty. You can type up to $msg_form_char_limit characters.</b></span>};
}
else {
if (defined $length_msg_form and $ENV{REQUEST_METHOD} eq 'POST'){
- $msg_form =~ tr/\r//d; # if we dont do this, ^M character in plain text mail
- my $gpg = new GPG(gnupg_path => "/usr/bin", homedir => $GPG_HOMEDIR);
- $enc_msg = $gpg->encrypt("$linkuser:\n\n$msg_form", $mymail_gpgid) or die $gpg->error();
+ $msg_form =~ tr/\r//d; # if we dont do this, ^M character in plain text mail will show up
+ use Mail::GPG;
- if ($HAS_MAILSERVER){
- use Mail::Sendmail;
- my %mail = ( To => "$mymailaddr",
- From => "$mailsender",
+ my $gpgmail = Mail::GPG->new(
+ default_key_encrypt => $mailaddr,
+ default_key_id => $mailaddr,
+ gnupg_hash_init => {homedir=>$GPG_HOMEDIR},
+ debug => 0,
+ no_strict_7bit_encoding => 1,
+ );
+ my $rfc822date = GetRFC822Date();
+ my $mimentity = MIME::Entity->build (
+ Date => $rfc822date,
+ From => $mailsender,
Subject => '.',
- Message => "$enc_msg\n"
- );
- sendmail(%mail) or die $Mail::Sendmail::error;
- }
- else {
- use Net::SMTP;
- use Net::SMTPS;
- my $smtp = Net::SMTPS->new($mailsender_smtp, Port => $mailsender_port, doSSL => 'ssl', Debug_SSL => 0);
- my $mymailaddr_escaped = EscapeArobase($mymailaddr);
- my $mailsender_escaped = EscapeArobase($mailsender);
-
- $smtp->auth($mailsender, $mailsender_pw) or die;
- $smtp->mail($mailsender) or die "Net::SMTP module has broke: $!.";
- if ($smtp->to($mymailaddr)){
- $smtp->data();
- $smtp->datasend("From: $mailsender_escaped\n");
- $smtp->datasend("To: $mymailaddr_escaped\n");
- $smtp->datasend("Subject: .\n");
- $smtp->datasend("\n");
- $smtp->datasend("$enc_msg\n");
- $smtp->dataend();
+ To => $mailaddr,
+ Data => [ "This is a message from $linkuser:\n\n$msg_form" ],
+ Charset => 'utf-8',
+ );
+
+ if ( my $fh = $cgi_query_get->upload('fupload') ){
+ my $fullfn = $cgi_query_get->param('fupload');
+ $fullfn =~ s/[^A-Za-z_0-9\.\-]/_/g;
+ $fullfn =~ s/__+/_/g;
+ my $fpath = $cgi_query_get->tmpFileName($fh) or die "can't get uploaded file name: $!";
+ my $fsize = -s $fpath;
+ if ($fsize > $fsize_limit){
+ die 'ERROR: File is too big (>100MB).'; # I don't think we'll se this error, it'll return 413 instead
}
- else {
- die $smtp->message();
+
+ my $mimetype = $cgi_query_get->uploadInfo($fh)->{'Content-Type'};
+ if (not $mimetype =~ /^([\w]+)\/([\w]+)$/){
+ die "Unrecognized MIME type";
}
+
+ $mimentity->attach(
+ Type => $mimetype,
+ Description => $fullfn,
+ Encoding => 'base64',
+ Path => $fpath,
+ Filename => $fullfn,
+ ) or die "can't attach file to main MIME entity: $!";
}
- unlink $linkfilename;
+ my $encrypted_mime_blob = $gpgmail->mime_encrypt(entity => $mimentity);
+ my $encrypted_mime = $encrypted_mime_blob->as_string;
+
+ use Net::SMTP;
+ use Net::SMTPS;
+ if ($HAS_MAILSERVER){
+ $smtp = Net::SMTP->new(Host => 'localhost');
+ }
+ else {
+ $smtp = Net::SMTPS->new($mailsender_smtp, Port => $mailsender_port, doSSL => 'ssl', Debug_SSL => 0);
+ $smtp->auth($mailsender, $mailsender_pw) or die "$!";
+ }
+
+ $smtp->mail($mailsender) or die "Net::SMTP module has broke: $!.";
+ if ($smtp->to($mailaddr)){
+ $smtp->data($encrypted_mime);
+ $smtp->dataend();
+ $smtp->quit();
+ }
+ else {
+ die $smtp->message();
+ }
+
+ if ($0 =~ /([\w]+)\.cgi$/){
+ unlink "$1.cgi";
+ }
print "Location: /merci/index.html\n\n";
}
}
-print "Content-type: text/html", "\n\n";
-print qq{<!DOCTYPE html>
+print "Content-type: text/html", "\n\n",
+qq{<!DOCTYPE html>
<html>
<head>
<link rel="icon" sizes="48x48" type="image/ico" href="/favicon.ico">
<link rel="stylesheet" type="text/css" href="/styles.css">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta charset="UTF-8">
- <title>{link_web_title}</title>
+ <title>GPIGEON - Message form</title>
</head>
<body>
- <p id="msgbelow">{type_msg_below}:</p>
- <form method="POST">
+ <p id="msgbelow">Type your message below:</p>
+ <form method="POST" enctype="multipart/form-data">
<textarea id="msg" wrap="off" cols="50" rows="30" name="msg"></textarea><br>
-};
-if (defined $error_processing_msg){
- printf $error_processing_msg;
-}
-printf q{
- <br>
- <input id="sendbtn" type="submit" value="{link_send_btn}">
+ $form_error_notif
+ <label for="filechoice" id="msgbelow">
+ (Optional) file upload:
+ <input id="filechoice" type="file" name="file">
+ </label>
+ <input id="sendbtn" type="submit" value="Send">
</form>
</body>
-</html> };
+</html>};
diff --git a/styles.css b/styles.css
index 7f8770d..50ab8ad 100644
--- a/styles.css
+++ b/styles.css
@@ -10,6 +10,7 @@ body{
}
h1, #msgbelow{
+ display:block;
text-align:center;
}
@@ -40,6 +41,14 @@ h1, #msgbelow{
border:1px solid black;
}
+#logoutbtn {
+ display: inline;
+ float:right;
+ top: 0;
+ right: 0;
+ position:absolute;
+}
+
#msg{
display:block;
margin-left:auto;
@@ -64,7 +73,7 @@ h1, #msgbelow{
color:red;
}
-#loginbox {
+#loginbox #loginerr{
border:none;
margin-right:auto;
margin-left:auto
@@ -115,6 +124,10 @@ h1, #msgbelow{
font-size:0.8em;
}
+ h1{
+ font-size:1.5em;
+ }
+
#linkstable th,td{
padding:3px;
}
@@ -130,6 +143,13 @@ h1, #msgbelow{
line-height:15px;
}
+ #logoutbtn {
+ float:none;
+ top:unset;
+ right:unset;
+ position:revert;
+ }
+
#mailfield{
padding: 3px;
}