Compare commits
54 commits
Author | SHA1 | Date | |
---|---|---|---|
0f29851a37 | |||
77819962cc | |||
838d9da904 | |||
99868f3fe7 | |||
ec299f915f | |||
47065f1c07 | |||
dd26aa599e | |||
74a654ea5c | |||
b7f0e62177 | |||
9c0fcc3528 | |||
6d16b0a97d | |||
b40f3e7001 | |||
c237b9d8c5 | |||
d5da9a9574 | |||
968a288866 | |||
![]() |
47d733b2f4 | ||
12d506219a | |||
72a3b42d36 | |||
![]() |
ac77cbfe4b | ||
338c4c2771 | |||
![]() |
1d53129435 | ||
![]() |
deb4318cd9 | ||
9af44501cc | |||
![]() |
d67de26e90 | ||
82422e6d37 | |||
a804518ef6 | |||
e62bcfa9d8 | |||
5605143ffa | |||
4b06627b0a | |||
4fcd649b0b | |||
dcea6b2a24 | |||
f52dcbb721 | |||
b8dd0be83b | |||
c8f7473690 | |||
92c502b4a6 | |||
5aece18736 | |||
e8f03c430c | |||
2d9e3fc94c | |||
e28e8f54f8 | |||
6d5632ee81 | |||
e361669b87 | |||
80ef5e6ba2 | |||
db06f1cdc4 | |||
7ef35ba9bd | |||
5fbb1f5257 | |||
868ba54822 | |||
84ec3c9bc1 | |||
b39bd3bc5b | |||
955985b825 | |||
9c8749e664 | |||
957b87161c | |||
300f9fe78c | |||
cdb7bdd148 | |||
81e2129dd5 |
28 changed files with 756 additions and 309 deletions
19
.github/workflows/c-cpp.yml
vendored
Normal file
19
.github/workflows/c-cpp.yml
vendored
Normal 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
37
.github/workflows/sakisafe_http.yml
vendored
Normal 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
|
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -3,3 +3,15 @@
|
|||
obj/
|
||||
.clangd
|
||||
.depend
|
||||
http/f/*
|
||||
blib/
|
||||
pm_to_blib
|
||||
Makefile
|
||||
Makefile.old
|
||||
MANIFEST*
|
||||
!MANIFEST.SKIP
|
||||
META.*/
|
||||
MYMETA.*
|
||||
pm_to_blib
|
||||
sakisafe.log
|
||||
f/
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -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
|
||||
|
|
122
README.md
122
README.md
|
@ -6,34 +6,133 @@
|
|||
|
||||
* Written in perl
|
||||
* Can be used as pastebin
|
||||
* Or as a URL shorter
|
||||
* Runs with CGI
|
||||
* Tor access ;)
|
||||
* If running OpenBSD, sakisafecli will use pledge()
|
||||
* Easy installation (just a simple daemon and use a reverse proxy)
|
||||
* Does not bully Tor users ;)
|
||||
|
||||
|
||||
## Installation:
|
||||
# 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.
|
||||
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
|
||||
|
||||
sakisafecli is a command line interface for sakisafe servers (and
|
||||
other file upload services).
|
||||
other file upload services). It also supports file uploading via scp
|
||||
(ssh).
|
||||
|
||||
## Features
|
||||
|
||||
* Written in C so is fast.
|
||||
* 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
|
||||
|
||||

|
||||
|
||||
TODO: Add the thing to Debian repositories ;)
|
||||
|
||||
|
||||
# Contributing
|
||||
|
||||
Just create a pull request in GitHub or send a diff file.
|
||||
|
||||
# Donate
|
||||
|
||||
Thanks!
|
||||
|
@ -41,3 +140,4 @@ Thanks!
|
|||
**Bitcoin**: bc1qghl6f27dpgktynpvkrxte2s3gm9pcv8vlwuzum
|
||||
|
||||
**Monero**: 47QTumjtqJabbo1s9pLDdXeJarLVLfs1AaEcbi1xrEiV852mqcbe5AHLNXTk7tH9MscxcxQDfJQnvH5LpxvfgwSJQZ3zbS6
|
||||
|
||||
|
|
15
SERVERS.org
15
SERVERS.org
|
@ -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
14
http/.perltidyrc
Normal 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
15
http/Dockerfile
Normal 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
17
http/Makefile.PL
Normal 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
1
http/hypnotoad.pid
Normal file
|
@ -0,0 +1 @@
|
|||
16143
|
|
@ -1,28 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# This file is part of sakisafe.
|
||||
# lainsafe 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.
|
||||
|
||||
# lainsafe 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 lainsafe. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
if ($ENV{REQUEST_METHOD} eq "POST") {
|
||||
do "./upload.cgi";
|
||||
exit;
|
||||
}
|
||||
|
||||
my $SITE_URL = $ENV{REMOTE_ADDR};
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
open(my $fh, "<index.html");
|
||||
|
||||
print while <$fh>;
|
|
@ -1,27 +0,0 @@
|
|||
<!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>
|
||||
<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' $SITE_URL</code>
|
||||
<p>Shorten URL:</p>
|
||||
<code>curl -F 'url=https://example.org' $SITE_URL</code>
|
||||
<p>Post your text directly</p>
|
||||
<code>curl -F 'file=@-' $SITE_URL</code>
|
||||
<div class="left">
|
||||
<h2>Or just upload a file here</h2>
|
||||
<form ENCTYPE='multipart/form-data' method='post' action='upload.cgi'>
|
||||
<input type='file' name='file' size='30'/>
|
||||
<input type='submit' value='upload'/>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
24
http/init/sakisafe_bsd
Normal file
24
http/init/sakisafe_bsd
Normal 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
BIN
http/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -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;
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
268
http/sakisafe.pl
Executable file
268
http/sakisafe.pl
Executable file
|
@ -0,0 +1,268 @@
|
|||
#!/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 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';
|
||||
|
||||
# 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 $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
|
||||
);
|
||||
}
|
||||
|
||||
if ( List::MoreUtils::any { /$c->req->headers->header('X-Forwarded-For')/ } uniq @BANNED ) {
|
||||
$c->render(
|
||||
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 = "";
|
||||
}
|
||||
|
||||
# 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 $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' 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
|
108
http/upload.cgi
108
http/upload.cgi
|
@ -1,108 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
# This file is part of sakisafe.
|
||||
|
||||
# sakisafe 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.
|
||||
|
||||
# sakisafe 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 sakisafe. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use CGI;
|
||||
use CGI::Carp qw(fatalsToBrowser);
|
||||
|
||||
my $q = CGI->new;
|
||||
|
||||
my $filename = $q->param('file');
|
||||
my $url = $q->param('url');
|
||||
|
||||
my $upload_dir = "files/";
|
||||
|
||||
$size = $ENV{CONTENT_LENGTH};
|
||||
|
||||
# Configuration
|
||||
|
||||
our $MAX_SIZE = 1024*1024*100; # Change for your size
|
||||
our $MAX_SIZE_MB = $MAX_SIZE / 1024 / 1024; # Don't change this
|
||||
|
||||
our @not_allowed_extensions = qw(sh out exe);
|
||||
|
||||
print $q->header();
|
||||
|
||||
# do something better
|
||||
if ($url ne "") {
|
||||
goto url_shorter;
|
||||
}
|
||||
|
||||
if ($filename eq "" || $ENV{REQUEST_METHOD} eq "GET") {
|
||||
print("What are you looking for?");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($filename) {
|
||||
if ($size > $MAX_SIZE) {
|
||||
print("Max size for a file is $MAX_SIZE_MB MBs");
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
my @chars = ("A"..."z","a"..."z");
|
||||
my $dirname;
|
||||
my $extension = $filename;
|
||||
|
||||
$dirname .= $chars[rand @chars] for 1..8;
|
||||
$extension =~ s/.*\.//;
|
||||
$filename .= ".notcgi" if $extension eq "cgi";
|
||||
|
||||
mkdir("$upload_dir/$dirname");
|
||||
my $upload_filehandle = $q->upload("file");
|
||||
|
||||
# onion urls will be http
|
||||
my $prot = length $ENV{HTTPS} ? "https" : "http";
|
||||
|
||||
my $allowed_extension = 1;
|
||||
|
||||
foreach (@not_allowed_extensions) {
|
||||
if ($filename =~ /\.$_$/i) {
|
||||
$allowed_extension = 0;
|
||||
last;
|
||||
}
|
||||
|
||||
}
|
||||
if ($filename eq "-") {
|
||||
$filename .= ".txt"; # for pastes
|
||||
}
|
||||
if ($allowed_extension) {
|
||||
|
||||
open(FILE,">$upload_dir/$dirname/$filename");
|
||||
binmode(FILE);
|
||||
while (<$upload_filehandle>) {
|
||||
print FILE;
|
||||
}
|
||||
close FILE;
|
||||
$filename =~ s/ /%20/g;
|
||||
|
||||
print $prot. "://" . $ENV{HTTP_HOST} . "/$upload_dir$dirname/$filename" . "\n";
|
||||
} else {
|
||||
print "The file extension .$extension is not allowed in this instance.";
|
||||
}
|
||||
exit;
|
||||
} elsif ($url != "" && !$filename) {
|
||||
url_shorter:
|
||||
my $template = "<meta http-equiv=\"Refresh\" content=\"0; url='$url'\"/>";
|
||||
my @chars = ("A"..."z","a"..."z",1..9);
|
||||
my $dirname;
|
||||
$dirname .= $chars[rand @chars] for 1..4;
|
||||
mkdir($dirname);
|
||||
open(my $fh, ">$dirname/index.html");
|
||||
print $fh $template;
|
||||
my $prot = length $ENV{HTTPS} ? "https" : "http";
|
||||
print $prot. "://" . $ENV{HTTP_HOST} . "/$dirname" . "\n";
|
||||
exit;
|
||||
}
|
|
@ -1,8 +1,18 @@
|
|||
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
|
||||
PROG += sakisafecli
|
||||
SRCS += funcs.c sakisafecli.c config.c
|
||||
MAN += sakisafecli.1 sakisafeclirc.5
|
||||
LDADD += -lpthread -lcurl -lconfig -L/usr/local/lib -fPIC
|
||||
PREFIX = /usr/local
|
||||
|
||||
# Use libbsd features if wanted
|
||||
use-libbsd ?= no
|
||||
.if ${use-libbsd} == "yes"
|
||||
CFLAGS += -Duse_libbsd
|
||||
LDADD += -lbsd
|
||||
.endif
|
||||
|
||||
BINMODE = 755
|
||||
BINDIR = $(PREFIX)/bin
|
||||
MANDIR = $(PREFIX)/man/man
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
@ -28,13 +28,11 @@ print_config()
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
config_t runtime_config;
|
||||
void
|
||||
parse_config_file(FILE *config)
|
||||
{
|
||||
|
||||
config_t runtime_config;
|
||||
|
||||
config_init(&runtime_config);
|
||||
config_read(&runtime_config, config);
|
||||
config_setting_t *cur;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1,54 +1,152 @@
|
|||
#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)
|
||||
write_data(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
memcpy(userp, buffer, nmemb*size);
|
||||
memcpy(userp, buffer, nmemb * size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
print_usage()
|
||||
{
|
||||
printf("USAGE: sakisafecli [-p socks proxy|-P http proxy] [-x] [-s] [-6|-4] [--server] FILE\n");
|
||||
printf("USAGE: sakisafecli [-p socks proxy|-P http proxy] [-x] [-s] "
|
||||
"[-6|-4] [--server] FILE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_help()
|
||||
{
|
||||
printf("-s|--server: specifies the sakisafe 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. 127.0.0.1:9050",
|
||||
"-6|--ipv6: uses IPv6 only",
|
||||
"-4|--ipv6: uses IPv4 only",
|
||||
"-S|--silent: doesn't print progress",
|
||||
"-x|--paste: read file from stdin",
|
||||
"-C: print current settings",
|
||||
"-h|--help: print this message.\n");
|
||||
printf("-s|--server: specifies the sakisafe "
|
||||
"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. 127.0.0.1:9050",
|
||||
"-6|--ipv6: uses IPv6 only",
|
||||
"-4|--ipv6: uses IPv4 only",
|
||||
"-S|--silent: doesn't print progress",
|
||||
"-x|--paste: read file from stdin",
|
||||
"-C: print current settings",
|
||||
"-h|--help: print this message.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
size_t
|
||||
progress(void *clientp,
|
||||
double dltotal,
|
||||
double dlnow,
|
||||
double ultotal,
|
||||
double ulnow)
|
||||
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)",ulnow,ultotal,
|
||||
ulnow*100/ultotal);
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -26,6 +26,6 @@ extern bool http_proxy_flag;
|
|||
extern bool ipv6_flag;
|
||||
extern bool ipv4_flag;
|
||||
extern bool silent_flag;
|
||||
extern config_t runtime_config;
|
||||
extern char *ssh_key_path;
|
||||
extern config_t runtime_config;
|
||||
#endif /* OPTIONS_H */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -8,24 +8,31 @@
|
|||
#include <unistd.h>
|
||||
#include <curl/curl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef use_libbsd
|
||||
#include <bsd/string.h>
|
||||
#endif
|
||||
#include "curl/easy.h"
|
||||
#include "options.h"
|
||||
#include "config.h"
|
||||
#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;
|
||||
config_t runtime_config;
|
||||
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)
|
||||
{
|
||||
|
@ -36,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];
|
||||
|
@ -55,7 +60,7 @@ main(int argc, char **argv)
|
|||
fclose(fp);
|
||||
}
|
||||
} else {
|
||||
#if defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(use_libbsd)
|
||||
strlcpy(config_location, sakisafeclirc_env, 512);
|
||||
#else /* Linux sucks! */
|
||||
strncpy(config_location, sakisafeclirc_env, 512);
|
||||
|
@ -68,26 +73,20 @@ main(int argc, char **argv)
|
|||
}
|
||||
/* libcurl initialization */
|
||||
|
||||
CURL *easy_handle = curl_easy_init();
|
||||
curl_mime *mime;
|
||||
mime = curl_mime_init(easy_handle);
|
||||
easy_handle = curl_easy_init();
|
||||
|
||||
if(!easy_handle) {
|
||||
fprintf(stderr, "Error initializing libcurl\n");
|
||||
return -1;
|
||||
}
|
||||
if(!mime) {
|
||||
fprintf(stderr, "Error initializing curl_mime\n");
|
||||
}
|
||||
|
||||
if(argc == optind) {
|
||||
print_usage();
|
||||
free(buffer);
|
||||
curl_easy_cleanup(easy_handle);
|
||||
curl_mime_free(mime);
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_sakisafe_options();
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{ "server", required_argument, 0, 's' },
|
||||
|
@ -157,24 +156,23 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if(access(argv[optind], F_OK) && !paste_flag) {
|
||||
fprintf(stderr, "Error opening file\n");
|
||||
fprintf(stderr, "Error opening file: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* If using SCP, set the ssh key */
|
||||
if(protocol == CURLPROTO_SCP && ssh_key_path != NULL) {
|
||||
curl_easy_setopt(
|
||||
easy_handle, CURLOPT_SSH_PRIVATE_KEYFILE, ssh_key_path);
|
||||
}
|
||||
|
||||
/* Proxy options */
|
||||
|
||||
if(socks_proxy_flag && http_proxy_flag) {
|
||||
|
@ -184,8 +182,7 @@ main(int argc, char **argv)
|
|||
curl_easy_setopt(easy_handle, CURLOPT_PROXY, socks_proxy_url);
|
||||
curl_easy_setopt(
|
||||
easy_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
|
||||
} else if(http_proxy_flag && ((protocol == CURLPROTO_HTTP) ||
|
||||
(protocol == CURLPROTO_HTTPS))) {
|
||||
} else if(http_proxy_flag && protocol == CURLPROTO_HTTP) {
|
||||
curl_easy_setopt(easy_handle, CURLOPT_PROXY, http_proxy_url);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||
}
|
||||
|
@ -200,7 +197,12 @@ main(int argc, char **argv)
|
|||
curl_easy_setopt(
|
||||
easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
|
||||
|
||||
/* Form parameters */
|
||||
/* Common options for both HTTP and SCP transfers */
|
||||
|
||||
curl_easy_setopt(easy_handle, CURLOPT_NOPROGRESS, silent_flag);
|
||||
struct progress mem;
|
||||
curl_easy_setopt(easy_handle, CURLOPT_XFERINFODATA, &mem);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_XFERINFOFUNCTION, progress);
|
||||
|
||||
/* File name */
|
||||
|
||||
|
@ -210,65 +212,20 @@ main(int argc, char **argv)
|
|||
|
||||
/* Process HTTP uploads */
|
||||
|
||||
if(protocol == CURLPROTO_HTTP || protocol == CURLPROTO_HTTPS) {
|
||||
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_setopt(easy_handle, CURLOPT_NOPROGRESS, silent_flag);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_PROGRESSFUNCTION, progress);
|
||||
|
||||
curl_easy_setopt(easy_handle, CURLOPT_MIMEPOST, mime);
|
||||
curl_easy_perform(easy_handle);
|
||||
if(!silent_flag)
|
||||
putchar('\n');
|
||||
puts(buffer);
|
||||
curl_mime_free(mime);
|
||||
|
||||
if(protocol == CURLPROTO_HTTP) {
|
||||
upload_file_http(argc, argv);
|
||||
}
|
||||
/* Process SCP uploads */
|
||||
else if(protocol == CURLPROTO_SCP) {
|
||||
char path[256];
|
||||
char *filename = argv[optind];
|
||||
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, true);
|
||||
FILE *fp = fopen(filename, "r");
|
||||
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_NOPROGRESS, silent_flag);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_PROGRESSFUNCTION, progress);
|
||||
curl_easy_setopt(
|
||||
easy_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)st.st_size);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_URL, path);
|
||||
curl_easy_perform(easy_handle);
|
||||
upload_file_scp(argc, argv);
|
||||
} else {
|
||||
puts("Unsupported protocol");
|
||||
return -1;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(easy_handle);
|
||||
|
||||
free(buffer);
|
||||
config_destroy(&runtime_config);
|
||||
free(buffer);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue