Compare commits

...
Sign in to create a new pull request.

41 commits

Author SHA1 Message Date
0f29851a37 Ready for 2.6.0 people 2025-02-23 18:25:42 +01:00
77819962cc I don't know why I haven't done this before.
- Added variables for instance information and contact
- Added favicon
2025-02-23 16:25:52 +01:00
838d9da904 Damn. For some reason the improved logging thing decided to nuke itself 2025-02-23 14:24:55 +01:00
99868f3fe7 fixed installation 2025-02-23 14:04:49 +01:00
ec299f915f updated the docs 2025-02-23 13:59:40 +01:00
47065f1c07 Added rc script for freebsd 2025-02-22 14:02:36 +01:00
dd26aa599e last try 2025-02-21 03:11:55 +01:00
74a654ea5c test 2025-02-21 03:06:50 +01:00
b7f0e62177 AIs are RETARDE 2025-02-21 03:01:54 +01:00
9c0fcc3528 Let's try this lol 2025-02-21 03:00:03 +01:00
6d16b0a97d Of course I had to do something bad 2025-02-21 02:53:48 +01:00
b40f3e7001 FINALLY fixed the logging thing and also logs to STDOUT
Got the client's actual IP address by using X-Forwarded-For header,
because some reverse proxy software (i.e. haproxy, relayd) will
override the IP address as the reverse proxy is the actual client.

Fixes #26
2025-02-21 02:52:01 +01:00
c237b9d8c5 a ver esta basura 2025-01-21 23:28:33 +01:00
d5da9a9574 I started addressing the issue I created 2 years ago about this shit
being unreadable. Hopefully this makes the thing more clear and
readable.

Some improvements could be done to the upload_file_* thing. As there's
really no need to pass argc and argv to those. And passing argv to
that is an overkill

Solution: To create a const char* variable and save the filename in
there and pass that to the functions. Simple as that. But i'm a lazy
motherfucker and I'm tired. Boss.
2025-01-21 23:04:41 +01:00
968a288866
Add support to ban extensions 2023-09-24 13:44:04 +02:00
Rawley
47d733b2f4
Add .perltidyrc, and format (#24)
* Add .perltidyrc, and format

* Format code

* Change tab size
2023-04-26 18:02:41 +02:00
12d506219a
Create c-cpp.yml
this is a test it might be nuked
2023-04-24 16:26:07 +02:00
72a3b42d36
Create c-cpp.yml
this is a test it might be nuked
2023-04-24 16:25:58 +02:00
Rawley
ac77cbfe4b
Improve logging (#23)
* Greatly improve logging with Mojo::Log
2023-03-24 08:05:01 +01:00
338c4c2771
Added POD documentation to sakisafe.pl 2023-03-15 14:54:25 +01:00
Rawley
1d53129435
Add Dockerfile (#22)
* added perl makefile

* fixup gitignore and eval

* add docker file
2023-03-14 13:14:48 +01:00
Rawley
deb4318cd9
Add Makefile.PL and allow banned IP's to be derived from a file (#21)
* added perl makefile

* fixup gitignore and eval
2023-03-13 14:18:46 +01:00
9af44501cc
Deleted a I that was there for free and removed an useless line 2023-03-10 14:57:17 +01:00
psydbernz
d67de26e90
added Linux-specific build hints (#20)
Co-authored-by: Bernz Pallek <dev@berniepallek.ca>
2023-03-09 16:36:18 +01:00
82422e6d37
Curl devs were very smart and decided to deprecated the
CURL_PROGRESSFUNCTION option that had 0 problems in my opinion and
decided to change it with CURL_XFERINFOFUNCTION thing which barely
works and had to do a very weird workaround so I don't get a floating
point exception just because. Well, it works and that's what matters.
2023-03-09 15:39:38 +01:00
a804518ef6
Fixed sakisafecli to work with latest commit 2023-02-15 12:57:18 +01:00
e62bcfa9d8
Added template for downlaod link in browsers, curl and similars just spit the link. 2023-02-13 21:30:11 +01:00
5605143ffa
Version 2023-02-12 13:46:33 +01:00
4b06627b0a
Goddamit, emacs 2023-02-12 13:44:09 +01:00
4fcd649b0b
Alright fixed more bugs 2023-02-12 13:42:18 +01:00
dcea6b2a24
Bug fix 2023-02-12 13:29:44 +01:00
f52dcbb721
Add colors to the warnings 2023-02-12 10:19:16 +01:00
b8dd0be83b
More verbose error messages using the 'Carp' module and $ERRNO 2023-02-12 10:02:36 +01:00
c8f7473690
Added support for OpenBSD's pledge because i was bored. 2023-02-11 11:43:49 +01:00
92c502b4a6
better language :) :) 2023-02-09 15:47:26 +01:00
5aece18736
Fixed the nginx configuration on README.md 2023-02-02 14:57:39 +01:00
e8f03c430c
Added MIME types and stuff so the browser is able to show the file [experimental] 2022-12-30 08:52:51 +01:00
2d9e3fc94c
this code should be refactored 2022-12-19 18:34:17 +01:00
e28e8f54f8
Updated documentation 2022-11-30 15:04:25 +01:00
6d5632ee81
Installation instructions in the readme 2022-11-23 19:45:34 +01:00
e361669b87
Added feature to ban IP addresses and also a logger 2022-11-22 15:23:03 +01:00
22 changed files with 672 additions and 176 deletions

19
.github/workflows/c-cpp.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: C/C++ CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: install dependencies
run: sudo apt-get update && sudo apt-get install -y bmake libcurl4-openssl-dev libconfig-dev
- name: bmake
run: bmake

37
.github/workflows/sakisafe_http.yml vendored Normal file
View file

@ -0,0 +1,37 @@
# This was written by an AI. HA!
# I hate writing yaml. I'm glad a computer can do it for me.
name: Test Mojolicious Application
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
web:
image: perl:latest
ports:
- 8080:8080
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y libmojolicious-perl liblist-moreutils-perl libmojolicious-plugin-renderfile-perl libpath-tiny-perl libmime-types-perl
- name: Start Sakisafe
run: |
hypnotoad http/sakisafe.pl
- name: Test Sakisafe
run: |
curl --retry 10 --retry-delay 5 --retry-connrefused http://localhost:8080
# LOLOLOLOLOLOLOLO
curl -X POST -F "file=@/etc/passwd" http://localhost:8080
- name: Read log entry
run: |
cat http/sakisafe.log

11
.gitignore vendored
View file

@ -4,3 +4,14 @@ obj/
.clangd
.depend
http/f/*
blib/
pm_to_blib
Makefile
Makefile.old
MANIFEST*
!MANIFEST.SKIP
META.*/
MYMETA.*
pm_to_blib
sakisafe.log
f/

View file

@ -1,4 +1,4 @@
Copyright $CURRENT_YEAR qorg11.
Copyright $CURRENT_YEAR SURAGU Enterprises
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

111
README.md
View file

@ -6,16 +6,92 @@
* Written in perl
* Can be used as pastebin
* Or as a URL shorter
* Easiy installation (just use fcgi)
* Runs with CGI
* Easy installation (just a simple daemon and use a reverse proxy)
* Does not bully Tor users ;)
## Installation:
1. Configure your webserver to run CGI
2. If running nginx, set `client_max_body_size` to the max size of
the file
2. There you go.
# Installation
sakisafe is written in Perl, so it is its first dependency. But if you're
using a real operating system you should have it by default.
1. install the dependencies using `cpan`:
~~~
cpan -i Mojolicious::Lite Mojolicious::Routes::Pattern Mojoliciuos::Plugin::RenderFile
~~~
If you're running Debian or FreeBSD you can install the dependencies with
your package manager:
~~~bash
apt install libmojolicious-perl libmojolicious-plugin-renderfile-perl liblist-moreutils-perl # Debian, Ubuntu...
pkg install p5-Mojolicious p5-List-MoreUtils p5-Path-Tiny # FreeBSD
# You'll have to run cpan to install the RenderFile plugin in FreeBSD
cpan -Ti Mojolicious::Plugin::Renderfile
~~~
2. Clone the repo and start the daemon:
~~~
git clone https://git.suragu.net/sosa/sakisafe
cd sakisafe/http
./sakisafe.pl daemon -m production
~~~
You can also use `hypnotoad` or `morbo` to run the thing:
~~~
morbo -l http://*:3000 sakisafe.pl.
hypnotoad sakisafe.pl # This will daemonize the thing in port 8080.
~~~
2.2. In FreeBSD, you can use the rc script located in
http/scripts/sakisafe_bsd to create a sakisafe service. The service is
loaded by the user "saki", whose home is `/usr/local/share/sakisafe`:
~~~bash
mkdir -p /usr/local/share/sakisafe
cp -r http/* /usr/local/share/sakisafe
cp http/init/sakisafe_bsd /usr/local/etc/rc.d
touch /var/run/sakisafe.pid
chmod 777 /var/run/sakisafe.pid # How to fix this? Please tell me
service sakisafe enable
service sakisafe start
~~~
Please contribute more init scripts for sakisafe!!! (for systemd,
openbsd...)
2.3. You can also use Docker. I am not a Docker advocate. But apparently
running "docker build-x" or something like that just works.
3. Create a 'f' directory in the directory sakisafe will run with
`mkdir f`. Make sure that the user which will run sakisafe.pl can
write in that directory.
By default, sakisafe will bind in 127.0.0.1 port 3000. Because that's
the default bind Mojolicious uses.
4. Create a proxy rule in nginx configuration (If you're using another
HTTP server, you're on your own.)
~~~conf
server {
server_name sakisafe.whatever.tld;
listen 443 ssl;
# ssl configuration here
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; # Important for logging!
proxy_set_header X-Forwarded-for $remote_addr; # Idem
proxy_pass http://127.0.0.1:3000$request_uri;
}
}
~~~
And restart nginx. Going to `sakisafe.whatever.tld` should work.
# sakisafecli
@ -26,23 +102,37 @@ other file upload services). It also supports file uploading via scp
## Features
* Written in C so is fast.
* HTTP and SCP support (FTP support is planned!)
* HTTP and SCP support (FTP support is planned)
* Highly configurable
* Lightweight
* If using OpenBSD, it will run `pledge()` for security reasons.
* As far as I know, runs in any *NIX operating system.
## Installation
### Compilation
Clone the repo and run `make` (or `bmake` in linux systems)
Clone the repo and run `make`.
#### Linux-specific
Use `bmake` instead of `make`, and you'll also need these deps:
* `libcurl-devel`
* `libconfig-dev`
* `libnghttp2-dev`
### Repositories
![](https://repology.org/badge/vertical-allrepos/sakisafe.svg)
TODO: Add the thing to Debian repositories ;)
# Contributing
Just create a pull request in GitHub or send a diff file.
# Donate
Thanks!
@ -50,3 +140,4 @@ Thanks!
**Bitcoin**: bc1qghl6f27dpgktynpvkrxte2s3gm9pcv8vlwuzum
**Monero**: 47QTumjtqJabbo1s9pLDdXeJarLVLfs1AaEcbi1xrEiV852mqcbe5AHLNXTk7tH9MscxcxQDfJQnvH5LpxvfgwSJQZ3zbS6

View file

@ -1,10 +1,9 @@
* Known lainsafe instances
* Known sakisafe instances
In this document i'll add all the lainsafe instance i know :)
In this document i'll add all the sakisafe instance i know :)
- https://lainsafe.delegao.moe
- https://lainsafe.duckdns.org (don't use it, old lainsafe version
and a bit incompatible with lainsafecli)
- https://lainsafe.kalli.st
- http://lainsafe.kallist4mcluuxbjnr5p2asdlmdhaos3pcrvhk3fbzmiiiftwg6zncid.onion/ (onion mirror)
- http://gnaumuq27fagoo24pb2mmf25rdic7lrthq2fsfolgrpzycc2hwga.b32.i2p/
Feel free to add more. I do not know about many others.
- https://ss.suragu.net
- https://files.getimiskon.xyuz
-

14
http/.perltidyrc Normal file
View file

@ -0,0 +1,14 @@
-pbp # Start with Perl Best Practices
-w # Show all warnings
-iob # Ignore old breakpoints
-l=120 # 120 characters per line
-mbl=2 # No more than 2 blank lines
-i=5 # Indentation is 2 columns
-ci=2 # Continuation indentation is 2 columns
-vt=0 # Less vertical tightness
-pt=2 # High parenthesis tightness
-bt=2 # High brace tightness
-sbt=2 # High square bracket tightness
-wn # Weld nested containers
-isbc # Don't indent comments without leading space
-nst # Don't output to STDOUT

15
http/Dockerfile Normal file
View file

@ -0,0 +1,15 @@
FROM perl:latest AS build
EXPOSE 3000
COPY . /sakisafe
COPY ./public /sakisafe/public
WORKDIR /sakisafe
RUN perl "Makefile.PL"
RUN make install
RUN cpan List::MoreUtils Path::Tiny MIME::Types Mojolicious Mojolicious::Plugin::RenderFile Mojolicious::Routes::Pattern
FROM build
CMD ["perl", "sakisafe.pl", "daemon"]

17
http/Makefile.PL Normal file
View file

@ -0,0 +1,17 @@
use v5.36;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'sakisafe',
CONFIGURE_REQUIRES => {
"Mojolicious" => 0,
"List::MoreUtils" => 0,
"Term::ANSIColor" => 0,
"MIME::Types" => 0,
"Path::Tiny" => 0,
"Mojolicious::Plugin::RenderFile" => 0,
"Mojolicious::Routes::Pattern" => 0
},
EXE_FILES => ['sakisafe.pl']
);

1
http/hypnotoad.pid Normal file
View file

@ -0,0 +1 @@
16143

24
http/init/sakisafe_bsd Normal file
View file

@ -0,0 +1,24 @@
#
# Add the following lines to /etc/rc.conf to enable sakisafe:
#
#sakisafe_enable="YES"
. /etc/rc.subr
name="sakisafe"
rcvar="sakisafe_enable"
load_rc_config $name
: ${sakisafe_user:=saki}
: ${sakisafe_group:=saki}
: ${sakisafe_enable:=NO}
: ${sakisafe_flags:= -P /var/run/sakisafe.pid -f /usr/local/bin/morbo -l http://*:3000 /usr/local/share/sakisafe/sakisafe.pl }
: ${sakisafe_chdir:= /usr/local/share/sakisafe }
command="/usr/sbin/daemon"
command_args="${sakisafe_flags}"
pidfile="/var/run/${name}.pid"
PATH="${PATH}"
run_rc_command "$1"

BIN
http/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,4 +1,4 @@
p {
p, ul, li {
color: white;
display: block;
}
@ -24,7 +24,8 @@ body {
}
h1, h2 {
color: #e3e3e3;
color: #e3e3e3;
font-family: monospace;
}
.left {
position: absolute;

View file

@ -1,89 +1,268 @@
#!/usr/bin/perl
#!/usr/bin/env perl
# This file is part of sakisafe.
use if $^O eq "openbsd", OpenBSD::Pledge, qw(pledge);
use Mojolicious::Lite -signatures;
use Mojolicious::Routes::Pattern;
use v5.36;
use Mojo::Log;
use Time::HiRes;
use List::MoreUtils qw(uniq);
use Carp;
use Term::ANSIColor;
use English;
use MIME::Types;
use Path::Tiny;
use warnings;
use experimental 'signatures';
use feature 'say';
plugin 'RenderFile';
my $MAX_SIZE = 1024 * 1024 * 100;
# OpenBSD promises.
pledge("stdio prot_exec cpath rpath wpath inet flock fattr")
if $^O eq "openbsd";
# INSTANCE CONFIGURATION
our $name = "sakisafe";
our $version = "2.6.0";
# Domain and port, for output link
our $domain = "XXXXXXXXXXX";
our $port = 443;
# Contact info
# Change this with whatever you want
our $contact_info = 'email: saki@sakisafe.lol';
# 1 GiBs
my $MAX_SIZE = 1024 * 1024 * 1000;
my @BANNED = eval { path('banned.txt')->slurp_utf8 }
or qw(); # Add banned IP addresses here
my @BANNED_EXTS = eval { path('banned_exts.txt')->slurp_utf8 }
or qw(); # Add forbidden files extensions here
my $dirname;
my $host;
my $link;
mkdir "f";
# Mojo logger
my $log = Mojo::Log->new(path => 'sakisafe.log', level => 'trace');
$log->color(1);
# Forward logs to STDERR or STDOUT while also writing to the `sakisafe.log` file.
$log->on(message => sub ($l, $level, @lines) {
my $time = time;
my ($s, $m, $h, $day, $month, $year) = localtime time;
$time = sprintf('%04d-%02d-%02d %02d:%02d:%08.5f', $year + 1900, $month + 1, $day, $h, $m,
"$s." . ((split '.', $time)[1] // 0));
my $log_to_print = '[' . $time . '] ' . '[' . $level . '] ' . join(' ', @lines);
if ($level eq 'trace' || $level eq 'info') {
say $log_to_print;
} else {
print \*STDERR, $log_to_print . "\n";
}
}
);
# Function to handle file uploads
sub handle_file {
my $c = shift;
my $filedata = $c->param("file");
if ( $filedata->size > $MAX_SIZE ) {
return $c->render(
text => "Max upload size: $MAX_SIZE",
status => 400
);
}
my $c = shift;
my $filedata = $c->param("file");
if ( $filedata->size > $MAX_SIZE ) {
return $c->render(
text => "Max upload size: $MAX_SIZE",
status => 400
);
}
# Generate random string for the directory
my @chars = ( '0' .. '9', 'a' .. 'Z' );
$dirname .= $chars[ rand @chars ] for 1 .. 5;
my $filename = $filedata->filename;
mkdir( "f/" . $dirname );
$filename .= ".txt" if $filename eq "-";
$filedata->move_to( "f/" . $dirname . "/" . $filename );
my $host = $c->req->url->to_abs->host;
$c->res->headers->header(
'Location' => "http://$host/$dirname/" . $filedata->filename );
if ( List::MoreUtils::any { /$c->req->headers->header('X-Forwarded-For')/ } uniq @BANNED ) {
$c->render(
text => "http://$host/f/$dirname/" . $filename,
status => 201,
);
$dirname = "";
text =>
"Hi! Seems like the server admin added your IP address to the banned IP array."
. "As the developer of sakisafe, I can't do anything.",
status => 403
);
return;
}
# Generate random string for the directory
my @chars = ( '0' .. '9', 'a' .. 'Z' );
$dirname .= $chars[ rand @chars ] for 1 .. 5;
my $filename = $filedata->filename;
my ($ext) = $filename =~ /(\.[^.]+)$/;
if ( List::MoreUtils::any { /$ext/ } uniq @BANNED_EXTS ) {
$c->render( text => "You cannot this filetype.\n", status => 415 );
$log->info("Attempt to upload by banned extension: " . $c->req->headers->header('X-Forwarded-For'));
say $ext;
return;
}
$c->req->headers->header('X-Forwarded-For')
unless mkdir( "f/" . $dirname );
$filename .= ".txt" if $filename eq "-";
# TODO: get whether the server is http or https
# There's a CGI ENV variable for that.
my $host = $c->req->url->to_abs->host;
my $ua = $c->req->headers->user_agent;
$filedata->move_to( "f/" . $dirname . "/" . $filename );
$link = "http://$host/f/$dirname/$filename";
$c->stash( link => $link, host => $host, dirname => $dirname );
$c->res->headers->header( 'Location' => "$link" . $filename );
# Only give the link to curl, html template for others.
if ( $ua =~ m/curl/ || $ua eq "" ) {
$c->render(
text => $link . "\n",
status => 201,
);
$dirname = "";
} else {
$c->render(
template => 'file',
status => 201,
);
}
$log->info($c->req->headers->header('X-Forwarded-For') . " " . $dirname . "/" . $filename );
$dirname = "";
}
get '/' => 'index';
# Function to log uploaded files
get '/' => sub ($c) {
$c->stash(name => $name, contact_info => $contact_info, version => $version);
$c->render(template => 'index');
};
post '/' => sub ($c) { handle_file($c) };
# Allow files to be downloaded.
get '/f/:dir/:name' => sub ($c) {
my $captures = $c->req->url;
$captures =~ s/^.//;
my $filerender = Mojolicious::Plugin::RenderFile->new;
$c->render_file( filepath => $captures );
};
get '/f/:dir/#name' => sub ($c) {
my $dir = $c->param("dir");
my $file = $c->param("name");
my $ext = $file;
$ext =~ s/.*\.//;
my $path = "f/" . $dir . "/" . $file;
#carp "sakisafe warning: could not get file: $ERRNO" unless
$c->render( text => "file not found", status => 404 ) unless -e $path;
$c->render_file(
filepath => $path,
format => $ext,
content_disposition => 'inline'
);
}
;
app->log($log);
app->max_request_size( 1024 * 1024 * 100 );
post '/upload' => sub ($c) { handle_file($c) };
app->start;
# Index template
# By default Mojolicious gets the "directory root" from the "public"
# directory, so the css and the favicon from the "public" directory,
# in the root of this repo.
# Not sure why I have to do this filthy hack, could not get Mojolicious
# to get the template here. So a TODO is to fix this.
__DATA__
@@ file.html.ep
<!DOCTYPE html>
<html lang="en">
<head>
<title>sakisafe</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<center>
<h1>sakisafe</h1>
<h2>shitless file upload, pastebin and url shorter</h2>
<img src="saki.png"/>
<h2>LINK</h2>
<code><%= $link %></code>
</center>
<p>Running sakisafe 2.6.0</p>
</body>
</html>
@@ index.html.ep
% layout 'index', name => $name, contact_info => $contact_info, version => $version;
<!DOCTYPE html>
<html lang="en">
<head>
<title>sakisafe</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<center>
<h1>sakisafe</h1>
<h2>shitless file upload, pastebin and url shorter</h2>
<img src="saki.png"/>
<h2>USAGE</h2>
<p>POST a file:</p>
<code>curl -F 'file=@yourfile.png' <%= $c->req->url->to_abs->host; %></code>
<p>Post your text directly</p>
<code>curl -F 'file=@-' <%= $c->req->url->to_abs->host; %></code>
</center>
<div class="left">
<h2>Or just upload a file here</h2>
<form ENCTYPE='multipart/form-data' method='post' action='/upload'>
<input type='file' name='file' size='30'/>
<input type='submit' value='upload'/>
</form>
</div>
</body>
</html>
<html lang="en">
<head>
<title>sakisafe</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<center>
<h1>sakisafe</h1>
<h2>shitless file upload, pastebin and url shorter</h2>
<img src="saki.png"/>
<h2>USAGE</h2>
<p>POST a file:</p>
<code>curl -F 'file=@yourfile.png' https://<%= $c->req->url->to_abs->host; %></code>
<p>Post your text directly</p>
<code>curl -F 'file=@-' https://<%= $c->req->url->to_abs->host; %></code><br/>
<a href="https://git.suragu.net/svragv/sakisafe">Git repository</a>
</center>
<h2>FAQ</h2>
<p>(No one has ever asked these questions)</p>
<p><b>How long are the files stored?</b> Until the heat death of the universe</b></p>
<p><b>Do you log IP addresses?</b> Yes. Blame the people uploading illegal stuff to this</p>
<p><b>Do you log all the requests?</b> Nah. Only file uploads are logged.</p>
<p><b>Can you delete a file I uploaded?</b><p>That depends on the instance administrator</b></p>
<h2>Instance info</h2>
<ul>
<li>Name: <%= $name %></li>
<li>Contact info: <%= $contact_info%>
</ul>
<p>Running sakisafe <%=$version%></p>
<div class="left">
<h2>Or just upload a file here</h2>
<form ENCTYPE='multipart/form-data' method='post' action='/upload'>
<input type='file' name='file' size='30'/>
<input type='submit' value='upload'/>
</form>
</div>
</body>
</html>
__END__
=pod
=head1 sakisafe
sakisafe is a web application using the Mojolicious framework which
allow users to simply upload and share files.
=head2 synopsis
C<./sakisafe.pl daemon -m production>
This will start sakisafe in port 3000. Which should be proxied with
nginx or any reverse proxy software.
=head2 license
The Unlicense.
=head2 author
Raoul Vaughn
=cut

View file

@ -1,8 +1,7 @@
PROG += sakisafecli
SRCS += funcs.c sakisafecli.c config.c
MAN += sakisafecli.1 sakisafeclirc.5
LDADD += -lssl -lz -lpthread -lnghttp2 -lcurl -lconfig -lcrypto -L/usr/local/lib
LDADD += -lpthread -lcurl -lconfig -L/usr/local/lib -fPIC
PREFIX = /usr/local
# Use libbsd features if wanted

View file

@ -1,4 +1,8 @@
#pragma once
#include <curl/curl.h>
#include <libconfig.h>
#include <stdbool.h>
/* Parse the config file */
void
@ -6,4 +10,21 @@ parse_config_file(FILE *config);
/* Print the current settings */
void
print_config();
print_config();
/* Internal variables */
extern CURL *easy_handle;
extern char *buffer;
/* Config variables */
extern bool ipv6_flag, ipv4_flag, http_proxy_flag,
socks_proxy_flag, silent_flag, paste_flag;
extern char *http_proxy_url, *socks_proxy_url;
extern char *ssh_key_path;
extern char *server;
extern const char *path;

View file

@ -1,9 +1,14 @@
#include <curl/system.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <libconfig.h>
#include <curl/curl.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <getopt.h>
#include "sakisafecli.h"
#include "config.h"
size_t
write_data(void *buffer, size_t size, size_t nmemb, void *userp)
@ -27,9 +32,9 @@ print_help()
"server\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",
"-t|--token: Authentication token (https://u.kalli.st)",
"-P|--http-proxy: http proxy to use e.g. http://127.0.0.1:4444",
"-p|--socks-proxy: SOCK proxy to use e.g.I 127.0.0.1:9050",
"-p|--socks-proxy: SOCK proxy to use e.g. 127.0.0.1:9050",
"-6|--ipv6: uses IPv6 only",
"-4|--ipv6: uses IPv4 only",
"-4|--ipv6: uses IPv4 only",
"-S|--silent: doesn't print progress",
"-x|--paste: read file from stdin",
"-C: print current settings",
@ -37,16 +42,111 @@ print_help()
return;
}
void
progress(
void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
size_t
progress(void *clientp,
curl_off_t dltotal,
curl_off_t dlnow,
curl_off_t ultotal,
curl_off_t ulnow)
{
/* So I don't get a warning */
dltotal += 1;
dlnow += 1;
printf("\r%0.f uploaded of %0.f (\033[32;1m%0.f%%\033[30;0m)",
/* I don't know why the fuck I have to do this */
if(ultotal == 0) {
ultotal++;
}
printf("\r%li uploaded of %li (\033[32;1m%li%%\033[30;0m)",
ulnow,
ultotal,
ulnow * 100 / ultotal);
fflush(stdout);
return 0;
}
int
get_protocol(char *server)
{
if(strstr(server, "http://") != NULL || strstr(server, "https://"))
return CURLPROTO_HTTP;
else if(strstr(server, "scp://") != NULL)
return CURLPROTO_SCP;
else
return -1;
}
void
die(const char *msg)
{
fprintf(stderr, "%i: %s", errno, msg);
}
void
init_sakisafe_options()
{
ipv6_flag = http_proxy_flag,
socks_proxy_flag = paste_flag = silent_flag = false;
ipv4_flag = true;
ssh_key_path = NULL;
server = "https://meth.cat";
path = ".cache/sakisafelinks";
}
int
upload_file_http(int argc, char **argv)
{
curl_mime *mime;
mime = curl_mime_init(easy_handle);
curl_easy_setopt(easy_handle, CURLOPT_MIMEPOST, mime);
if(!mime) {
fprintf(stderr, "Error initializing curl_mime\n");
return -1;
}
curl_mimepart *file_data;
file_data = curl_mime_addpart(mime);
char *filename = argv[optind - 1];
/* Get file from stdin */
if(paste_flag)
filename = "/dev/stdin";
curl_mime_filedata(file_data, filename);
curl_mime_name(file_data, "file");
if(paste_flag)
curl_mime_filename(file_data, "-");
curl_easy_perform(easy_handle);
if(!silent_flag)
putchar('\n');
puts(buffer);
curl_mime_free(mime);
return 0;
}
int
upload_file_scp(int argc, char **argv)
{
curl_easy_setopt(easy_handle, CURLOPT_SSH_PRIVATE_KEYFILE, ssh_key_path);
char path[256];
char *filename = argv[optind];
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, true);
FILE *fp = fopen(filename, "r");
if(fp == NULL) {
fprintf(stderr, "%s", strerror(errno));
exit(-1);
}
struct stat st;
stat(argv[optind], &st);
snprintf(path, 256, "%s/%s", server, filename);
curl_easy_setopt(easy_handle, CURLOPT_READDATA, fp);
curl_easy_setopt(
easy_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)st.st_size);
int ret = curl_easy_perform(easy_handle);
putchar('\n');
if(ret != 0) {
fprintf(stderr, "%i: %s\n", ret, curl_easy_strerror(ret));
}
fclose(fp);
return 0;
}

View file

@ -22,3 +22,18 @@ progress(
/* Print config */
void
print_config();
int
init_sakisafe_options();
int
get_protocol(char *server);
int
die(char *msg);
int
upload_file_http(int argc, char **argv);
int
upload_file_scp(int argc, char **argv);

View file

@ -56,6 +56,6 @@ was rebranded to
.Sy sakisafecli
in 2022-05-05
.Sh AUTHORS
qorg11 <teru-sama at riseup dot net>
Raoul Vaughn <chief_keef at riseup dot net>
.Sh SEE ALSO
sakisafeclirc(5)

View file

@ -18,16 +18,20 @@
#include "funcs.h"
#include "sakisafecli.h"
CURL *easy_handle;
char *buffer;
/* Config variables */
bool ipv6_flag = false, ipv4_flag = false, http_proxy_flag = false,
socks_proxy_flag = false, silent_flag = false, paste_flag = false;
bool ipv6_flag, ipv4_flag, http_proxy_flag,
socks_proxy_flag, silent_flag, paste_flag;
char *http_proxy_url, *socks_proxy_url;
char *ssh_key_path = NULL;
char *ssh_key_path;
char *server;
const char *path;
char *server = "https://lainsafe.delegao.moe";
const char *path = ".cache/sakisafelinks";
int
main(int argc, char **argv)
@ -39,12 +43,10 @@ main(int argc, char **argv)
}
#endif
char *form_key = "file";
char *buffer = (char *)calloc(1024, sizeof(char));
buffer = (char *)calloc(1024, sizeof(char));
if(buffer == NULL) {
fprintf(stderr, "Error allocating memory!\n");
fprintf(stderr, "Error allocating memory for buffer!\n");
return -1;
}
char config_location[512];
@ -71,7 +73,7 @@ main(int argc, char **argv)
}
/* libcurl initialization */
CURL *easy_handle = curl_easy_init();
easy_handle = curl_easy_init();
if(!easy_handle) {
fprintf(stderr, "Error initializing libcurl\n");
@ -84,7 +86,7 @@ main(int argc, char **argv)
curl_easy_cleanup(easy_handle);
return -1;
}
init_sakisafe_options();
int option_index = 0;
static struct option long_options[] = {
{ "server", required_argument, 0, 's' },
@ -159,11 +161,16 @@ main(int argc, char **argv)
}
/* curl options */
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, buffer);
curl_easy_setopt(easy_handle, CURLOPT_URL, server);
if(curl_easy_setopt(easy_handle, CURLOPT_USERAGENT, "curl") != 0)
die("Error setting CURLOPT_USERAGENT");
if(curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data) != 0)
die("Error setting CURLOPT_WRITEFUNCTION");
if(curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, buffer) != 0)
die("error setting CURLOPT_WRITEDATA");
if(curl_easy_setopt(easy_handle, CURLOPT_URL, server) != 0)
die("error setting CURLOPT_URL");
int protocol = get_protocol(server);
/* Proxy options */
@ -193,7 +200,9 @@ main(int argc, char **argv)
/* Common options for both HTTP and SCP transfers */
curl_easy_setopt(easy_handle, CURLOPT_NOPROGRESS, silent_flag);
curl_easy_setopt(easy_handle, CURLOPT_PROGRESSFUNCTION, progress);
struct progress mem;
curl_easy_setopt(easy_handle, CURLOPT_XFERINFODATA, &mem);
curl_easy_setopt(easy_handle, CURLOPT_XFERINFOFUNCTION, progress);
/* File name */
@ -204,61 +213,11 @@ main(int argc, char **argv)
/* Process HTTP uploads */
if(protocol == CURLPROTO_HTTP) {
curl_mime *mime;
mime = curl_mime_init(easy_handle);
curl_easy_setopt(easy_handle, CURLOPT_MIMEPOST, mime);
if(!mime) {
fprintf(stderr, "Error initializing curl_mime\n");
}
curl_mimepart *file_data;
file_data = curl_mime_addpart(mime);
char *filename = argv[optind];
if(paste_flag)
filename = "/dev/stdin";
curl_mime_filedata(file_data, filename);
curl_mime_name(file_data, form_key);
if(paste_flag)
curl_mime_filename(file_data, "-");
curl_easy_perform(easy_handle);
if(!silent_flag)
putchar('\n');
puts(buffer);
curl_mime_free(mime);
upload_file_http(argc, argv);
}
/* Process SCP uploads */
else if(protocol == CURLPROTO_SCP) {
curl_easy_setopt(
easy_handle, CURLOPT_SSH_PRIVATE_KEYFILE, ssh_key_path);
char path[256];
char *filename = argv[optind];
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, true);
FILE *fp = fopen(filename, "r");
if(fp == NULL) {
fprintf(stderr, "%s", strerror(errno));
exit(-1);
}
struct stat st;
stat(argv[optind], &st);
snprintf(path, 256, "%s/%s", server, filename);
curl_easy_setopt(easy_handle, CURLOPT_READDATA, fp);
curl_easy_setopt(
easy_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)st.st_size);
int ret = curl_easy_perform(easy_handle);
putchar('\n');
if(ret != 0) {
fprintf(stderr, "%i: %s\n", ret, curl_easy_strerror(ret));
}
upload_file_scp(argc, argv);
} else {
puts("Unsupported protocol");
return -1;
@ -270,13 +229,3 @@ main(int argc, char **argv)
return 0;
}
int
get_protocol(char *server)
{
if(strstr(server, "http://") != NULL || strstr(server, "https://"))
return CURLPROTO_HTTP;
else if(strstr(server, "scp://") != NULL)
return CURLPROTO_SCP;
else
return -1;
}

View file

@ -2,6 +2,13 @@
#define SAKISAFECLI_H
#include <stdlib.h>
#include <stdio.h>
#include <curl/curl.h>
struct progress
{
char *_private;
size_t size;
};
size_t
write_data(void *buffer, size_t size, size_t nmemb, void *userp);
@ -15,9 +22,6 @@ store_link(const char *path, const char *buf);
void
print_help();
void
progress(
void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
void
parse_config_file(FILE *config);

View file

@ -61,13 +61,13 @@ and with the
127.0.0.1:9050
.Bd -literal -offset indent;
server="https://ls.qorg11.net"
server="https://ss.suragu.net"
socks_proxy="127.0.0.1:9050"
force_ipv4=true
use_socks_proxy=true
.Ed
.Sh AUTHORS
qorg11 <teru-sama at riseup dot net>
Raoul Vaughn <chief_keef at riseup dot net>
.Sh SEE ALSO
sakisafecli(1)