Compare commits

...

No commits in common. "8cff69ced0ceb4d3f58d8a30461c24135c824346" and "fc336b661f8f5580c93262adc469c8cd38e98c4d" have entirely different histories.

11 changed files with 644 additions and 466 deletions

5
.gitignore vendored
View file

@ -1,3 +1,6 @@
based
fbc
sfb
sfb.log
code
*.o
*.tar.gz

View file

@ -2,40 +2,40 @@
.SUFFIXES:
VERSION = 1.0
TARGET = based
MANPAGE = $(TARGET).1
TARGET = sfb
TARGET2 = fbc
PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man/man1
CFLAGS = -Os -march=native -mtune=native -pipe -s -std=c99 -pedantic -Wall
CFLAGS = -Os -march=native -mtune=native -pipe -s -std=c99 -pedantic -Wall -D_XOPEN_SOURCE=600
SRC = based.c
SRC = $(TARGET).c
SRC2 = $(TARGET2).c
$(TARGET): $(SRC)
$(CC) $(SRC) -o $@ $(CFLAGS)
$(TARGET): $(SRC) $(SRC2)
$(CC) $(SRC) -o $(TARGET) $(CFLAGS)
$(CC) $(SRC2) -o $(TARGET2) $(CFLAGS)
dist:
mkdir -p $(TARGET)-$(VERSION)
cp -R README.md $(MANPAGE) $(TARGET) $(TARGET)-$(VERSION)
cp -R README.md $(TARGET) $(TARGET2) $(TARGET)-$(VERSION)
tar -cf $(TARGET)-$(VERSION).tar $(TARGET)-$(VERSION)
gzip $(TARGET)-$(VERSION).tar
rm -rf $(TARGET)-$(VERSION)
install: $(TARGET)
install: $(TARGET) $(TARGET2)
mkdir -p $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(MANDIR)
cp -p $(TARGET) $(DESTDIR)$(BINDIR)/$(TARGET)
cp -p $(TARGET) $(TARGET2) $(DESTDIR)$(BINDIR)/$(TARGET)
chmod 755 $(DESTDIR)$(BINDIR)/$(TARGET)
cp -p $(MANPAGE) $(DESTDIR)$(MANDIR)/$(MANPAGE)
chmod 644 $(DESTDIR)$(MANDIR)/$(MANPAGE)
chmod 755 $(DESTDIR)$(BINDIR)/$(TARGET2)
uninstall:
rm $(DESTDIR)$(BINDIR)/$(TARGET)
rm $(DESTDIR)$(MANDIR)/$(MANPAGE)
rm $(DESTDIR)$(BINDIR)/$(TARGET2)
clean:
rm $(TARGET)
rm $(TARGET2)
all: $(TARGET)

View file

@ -1,25 +1,24 @@
# based
based is a command line tool to help A level students to revise base conversion.
# sfb
Suckless File Bin is a temporary file host, similar to [0x0.st](https://0x0.st) but is more minimal and simple. sfb is heavily inspired by [fiche](https://github.com/solusipse/fiche), it comes with a socket server(sfb) and socket client(fbc) that use a custom protocol(SFP, simple file protocol) which doesn't use HTTP to get around some VPS doesn't allow HTTP request to send files.
# Preview
![](https://r2.e-z.host/3c62bb3a-a8a9-43f6-afd6-553646f51dc4/8px2rilw.png)
`nginx.conf` has been provided so you can do reverse proxy.
`index.html` can be used for just nginx or flask server.
Notice for SFP, nginx is assumed to be used as index.txt will be created for each file sent(file path: OUTPUTDIR/ID/index.txt). And you are not required to use nginx for the HTTP server. With HTTP, no index.txt will be created, instead just a raw file as it will be handled by the flask server.
# Usage
```
Usage: based -f [from] -t [to] -n [number]
based is a command line tool to help A level students to revise base conversion.
Options:
-f [bin|oct|dec|hex] The base to convert from
-t [bin|oct|dec|hex] The base to convert to
-n [number] The number to convert (must be representable by 8 bits)
When from base is binary, the number must have 8 characters
When from base is octal, the number must have at most 3 characters
When from base is hexadecimal, the number must have 2 characters
When from base is decimal, the number must be a bigger than 0 and smaller than 256
```sh
sfb # SFP
pbc # SFP
python sfb.py # HTTP
```
# Dependencies
- For C Server:
None
- For Python HTTP server:
+ flask
+ flask-cors
# Building
You will need to run these with elevated privilages.
@ -32,4 +31,4 @@ $ make
Contributions are welcomed, feel free to open a pull request.
# License
This project is licensed under the GNU Public License v3.0. See [LICENSE](https://github.com/night0721/based/blob/master/LICENSE) for more information.
This project is licensed under the GNU Public License v3.0. See [LICENSE](https://github.com/night0721/sfb/blob/master/LICENSE) for more information.

48
based.1
View file

@ -1,48 +0,0 @@
.TH based 1 based\-VERSION
.SH NAME
based \- base conversion command line tool
.SH SYNOPSIS
.B based
.RB [ \-f ]
.RB [ \-t ]
.RB [ \-n ]
.RB [ \-h ]
.SH DESCRIPTION
based is a command line tool to help A level students to revise base conversion.
.SH OPTIONS
.TP
.B \-f [bin|oct|dec|hex]
Set the base of the number you want to convert from.
.TP
.B \-t [bin|oct|dec|hex]
Set the base of the number you want to convert to.
.TP
.B \-n
Set the number you want to convert.
.TP
.B \-h
Show help message.
.SH EXAMPLES
To convert the number 00001010 from binary to decimal, you can use the following command:
.PP
.B based \-f bin \-t dec \-n 00001010
.PP
To convert the number 12 from decimal to binary, you can use the following command:
.PP
.B based \-f dec \-t bin \-n 12
.PP
To convert the number 12 from decimal to octal, you can use the following command:
.PP
.B based \-f dec \-t oct \-n 12
.PP
.SH AUTHOR
Made by Night Kaly
.B <night@night0721.xyz>

387
based.c
View file

@ -1,387 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void bin_to_oct(char *binary) {
printf("Converting Binary to Octal:\n");
printf("First draw a table with 3 columns and list the index of 4, 2, 1.\n");
printf("2 1 | 4 2 1 | 4 2 1\n");
printf("Fill in the table with the binary number.\n");
printf("2 1 | 4 2 1 | 4 2 1\n");
printf("%c %c | %c %c %c | %c %c %c\n", binary[0], binary[1], binary[2], binary[3], binary[4], binary[5], binary[6], binary[7]);
printf("Convert each row to octal.\n");
char *first_col = malloc(sizeof(char) * 3);
char *second_col = malloc(sizeof(char) * 3);
char *third_col = malloc(sizeof(char) * 3);
strncpy(first_col, binary, 3);
first_col[2] = '\0';
strncpy(second_col, binary + 2, 3);
second_col[3] = '\0';
strncpy(third_col, binary + 5, 3);
third_col[3] = '\0';
printf("%o %o %o\n", (unsigned int) strtol(first_col, NULL, 2), (unsigned int) strtol(second_col, NULL, 2), (unsigned int) strtol(third_col, NULL, 2));
printf("Then, combine the octal numbers.\n");
printf("%o\n", (unsigned int) strtol(binary, NULL, 2));
}
void bin_to_dec(char *binary) {
printf("Converting Binary to Decimal:\n");
printf("List the Binary numbers out:\n");
printf("128 64 32 16 8 4 2 1\n");
printf("List the binary number.\n");
printf("128 64 32 16 8 4 2 1\n");
printf("%c %c %c %c %c %c %c %c\n", binary[0], binary[1], binary[2], binary[3], binary[4], binary[5], binary[6], binary[7]);
printf("Add the columns with 1.\n");
for (int i = 0; i < 8; i++) {
if (binary[i] == '1') {
printf("%d", 1 << (7 - i));
if (i < 7 ){
for (int j = i; j < 7; j++) {
// if all bits at the right are 0, don't print + sign
if (binary[j + 1] == '1') {
printf(" + ");
break;
}
}
}
}
}
printf(" = \n%d\n", (unsigned int) strtol(binary, NULL, 2));
}
void bin_to_hex(char *binary) {
printf("Converting Binary to Hexadecimal:\n");
printf("Split all bits into nibbles.\n");
printf("8 4 2 1 | 8 4 2 1\n");
printf("%c %c %c %c | %c %c %c %c\n", binary[0], binary[1], binary[2], binary[3], binary[4], binary[5], binary[6], binary[7]);
char *nibble1 = malloc(sizeof(char) * 5);
char *nibble2 = malloc(sizeof(char) * 5);
strncpy(nibble1, binary, 4);
nibble1[4] = '\0';
strncpy(nibble2, binary + 4, 4);
nibble2[4] = '\0';
printf("Convert each nibble to hexadecimal.\n");
printf("%X %X\n", (unsigned int) strtol(nibble1, NULL, 2), (unsigned int) strtol(nibble2, NULL, 2));
printf("Then, combine the hexadecimal numbers.\n");
printf("%X\n", (unsigned int) strtol(binary, NULL, 2));
}
char* oct_to_bin(char *octal) {
char *octal_copy = malloc(sizeof(char) * 4);
strncpy(octal_copy, octal, 3);
octal_copy[3] = '\0';
int octal_copy2[3];
for (int i = 0; i < 3; i++) {
octal_copy2[i] = octal[i] - '0';
}
char res[9];
printf("Converting Octal to Binary:\n");
printf("First draw a table with 3 columns and list the index of 4, 2, 1.\n");
printf("2 1 | 4 2 1 | 4 2 1\n");
printf("For each octal digit, convert it to binary by substracting the index.\n");
printf("For first octal digit:\n");
printf("%c -> ", octal[0]);
int rows[3] = { 4, 2, 1 };
for (int i = 1; i < 3; i++) {
if (octal_copy2[0] - rows[i] >= 0) {
printf("1");
res[i - 1] = '1';
octal_copy2[0] -= rows[i];
} else {
printf("0");
res[i - 1] = '0';
}
}
printf("\nFor second octal digit:\n");
printf("%c -> ", octal[1]);
for (int i = 0; i < 3; i++) {
if (octal_copy2[1] - rows[i] >= 0) {
printf("1");
res[i + 2] = '1';
octal_copy2[1] -= rows[i];
} else {
printf("0");
res[i + 2] = '0';
}
}
printf("\nFor third octal digit:\n");
printf("%c -> ", octal[2]);
for (int i = 0; i < 3; i++) {
if (octal_copy2[2] - rows[i] >= 0) {
printf("1");
res[i + 5] = '1';
octal_copy2[2] -= rows[i];
} else {
printf("0");
res[i + 5] = '0';
}
}
printf("\nThen, combine the binary numbers.\n");
res[8] = '\0';
printf("%s\n", res);
char *result = malloc(sizeof(char) * 9);
strncpy(result, res, 8);
result[8] = '\0';
return result;
}
void oct_to_dec(char *octal) {
printf("Converting Octal to Decimal:\n");
printf("In order to convert octal to decimal, we need to convert octal to binary first.\n");
char *res = oct_to_bin(octal);
bin_to_dec(res);
}
void oct_to_hex(char *octal) {
printf("Converting Octal to Hexadecimal:\n");
printf("In order to convert octal to hexadecimal, we need to convert octal to binary first.\n");
char *res = oct_to_bin(octal);
bin_to_hex(res);
}
char *dec_to_bin(char *decimal) {
printf("Converting Decimal to Binary:\n");
printf("List the Binary numbers out:\n");
printf("128 64 32 16 8 4 2 1\n");
printf("One by one from left to right, subtract the number with the binary number if it is big enough to do so. If it is able to subtract, subtract it and place 1 in the table, else place 0\n");
int dec = atoi(decimal);
int dec_copy = dec;
printf("\n%d", dec_copy);
for (int i = 0; i < 8; i++) {
if (dec_copy - (1 << (7 - i)) >= 0) {
printf(" - %d", 1 << (7 - i));
dec_copy -= (1 << (7 - i));
}
}
printf(" = 0\n");
char res[9];
printf("128 64 32 16 8 4 2 1\n");
for (int i = 0; i < 8; i++) {
if (dec - (1 << (7 - i)) >= 0) {
printf("1 ");
res[i] = '1';
dec -= (1 << (7 - i));
} else {
printf("0 ");
res[i] = '0';
}
}
printf("\nAfter the subtraction, the binary number is: %s\n", res);
char *res_copy = malloc(sizeof(char) * 9);
strncpy(res_copy, res, 8);
res_copy[8] = '\0';
return res_copy;
}
void dec_to_oct(char *decimal) {
printf("Converting Decimal to Octal:\n");
printf("In order to convert decimal to octal, we need to convert decimal to binary first.\n");
char *res = dec_to_bin(decimal);
printf("Then, convert the binary number to octal.\n");
bin_to_oct(res);
}
void dec_to_hex(char *decimal) {
printf("Converting Decimal to Hexadecimal:\n");
printf("Divide the decimal number by 16 take the quotient to be first digit of the hexadecimal number.\n");
printf("Take the remainder to be the second digit of the hexadecimal number.\n");
int dec = atoi(decimal);
printf("%d / 16 = %d remainder %d\n", dec, dec / 16, dec % 16);
printf("Then, convert the quotient and remainder to hexadecimal.\n");
printf("%d -> %X\n", dec / 16, dec / 16);
printf("%d -> %X\n", dec % 16, dec % 16);
printf("Then, combine the hexadecimal numbers.\n");
printf("%X%X\n", dec / 16, dec % 16);
}
char *hex_to_bin(char *hexadecimal) {
printf("Converting Hexadecimal to Binary:\n");
printf("Split the hexadecimal number into 2 characters.\n");
int char1 = hexadecimal[0] - '0';
int char2 = hexadecimal[1] - '0';
hexadecimal[0] = toupper(hexadecimal[0]);
hexadecimal[1] = toupper(hexadecimal[1]);
if (hexadecimal[0] >= 'A' && hexadecimal[0] <= 'F') {
char1 = hexadecimal[0] - 'A' + 10;
}
if (hexadecimal[1] >= 'A' && hexadecimal[1] <= 'F') {
char2 = hexadecimal[1] - 'A' + 10;
}
printf("%X %X\n", char1, char2);
printf("Convert each character to nibble.\n");
printf("For each character, subtract the number with the binary number if it is big enough to do so. If it is able to subtract, subtract it and place 1 in the table, else place 0.\n");
printf("List the Binary numbers out:\n");
printf("8 4 2 1 | 8 4 2 1\n");
char *res = malloc(sizeof(char) * 9);
printf("\nFirst character (%X):\n", char1);
printf("%X", char1);
int char1_copy = char1;
for (int i = 0; i < 4; i++) {
if (char1 - (1 << (3 - i)) >= 0) {
printf(" - %d", 1 << (3 - i));
char1 -= (1 << (3 - i));
}
}
printf(" = 0\n");
printf("8 4 2 1\n");
for (int i = 0; i < 4; i++) {
if (char1_copy - (1 << (3 - i)) >= 0) {
printf("1 ");
res[i] = '1';
char1_copy -= (1 << (3 - i));
} else {
printf("0 ");
res[i] = '0';
}
}
printf("\nSecond character (%X):\n", char2);
printf("%X", char2);
int char2_copy = char2;
for (int i = 0; i < 4; i++) {
if (char2 - (1 << (3 - i)) >= 0) {
printf(" - %d", 1 << (3 - i));
char2 -= (1 << (3 - i));
}
}
printf(" = 0\n");
printf("8 4 2 1\n");
for (int i = 0; i < 4; i++) {
if (char2_copy - (1 << (3 - i)) >= 0) {
printf("1 ");
res[i + 4] = '1';
char2_copy -= (1 << (3 - i));
} else {
printf("0 ");
res[i + 4] = '0';
}
}
res[8] = '\0';
printf("\nCombine the binary numbers.\n");
printf("%s\n", res);
return res;
}
void hex_to_oct(char *hexadecimal) {
printf("Converting Hexadecimal to Octal:\n");
printf("In order to convert hexadecimal to octal, we need to convert hexadecimal to binary first.\n");
char *res = hex_to_bin(hexadecimal);
printf("Then, convert the binary number to octal.\n");
bin_to_oct(res);
}
void hex_to_dec(char *hexadecimal) {
printf("Converting Hexadecimal to Decimal:\n");
printf("In order to convert hexadecimal to decimal, we need to convert hexadecimal to binary first.\n");
char *res = hex_to_bin(hexadecimal);
printf("Then, convert the binary number to decimal.\n");
bin_to_dec(res);
}
void usage(char **argv) {
printf("Usage: ./based -f [from] -t [to] -n [number]\n");
}
void validate_input(char **argv, char *choices[4]) {
if (strncmp(argv[1], "-f", 2) || strncmp(argv[3], "-t", 2) || strncmp(argv[5], "-n", 2)) {
// option not in right place
usage(argv);
}
// input validation
for (int i = 2; i < 6; i += 2) {
int found = 0;
for (int j = 0; j < 4; j++) {
if (strcmp(argv[i], choices[j]) == 0) {
found = 1;
break;
}
}
if (!found) {
printf("based: Unknown base -> %s\n", argv[i]);
usage(argv);
exit(1);
}
}
}
int main(int argc, char **argv) {
if (argc != 7) {
if (argc == 2 && strncmp(argv[1], "-h", 2) == 0) {
usage(argv);
printf("based is a command line tool to help A level students to revise base conversion.\n");
printf("Options:\n");
printf(" -f [bin|oct|dec|hex] The base to convert from\n");
printf(" -t [bin|oct|dec|hex] The base to convert to\n");
printf(" -n [number] The number to convert (must be representable by 8 bits)\n");
printf(" When from base is binary, the number must have 8 characters\n");
printf(" When from base is octal, the number must have at most 3 characters\n");
printf(" When from base is hexadecimal, the number must have 2 characters\n");
printf(" When from base is decimal, the number must be a bigger than 0 and smaller than 256\n");
return 0;
}
usage(argv);
return 1;
}
char *choices[4] = { "bin", "oct", "dec", "hex" };
validate_input(argv, choices);
char *from_base = argv[2];
char *to_base = argv[4];
char *number = argv[6];
if (!strcmp(from_base, to_base)) {
printf("based: Cannot convert from same bases.\n");
return 1;
}
if (strncmp(from_base, "bin", 3) == 0) {
if (strlen(number) != 8) {
printf("based: Binary number must be 8 bits. If it is a 7 bits number, add a 0 first.\n");
return 1;
}
if (strncmp(to_base, "oct", 3) == 0) {
bin_to_oct(number);
} else if (strncmp(to_base, "dec", 3) == 0) {
bin_to_dec(number);
} else if (strncmp(to_base, "hex", 3) == 0) {
bin_to_hex(number);
}
} else if (strncmp(from_base, "oct", 3) == 0) {
if (strlen(number) > 3) {
printf("based: Octal number must be 3 or less than 3 digits");
return 1;
}
if (strncmp(to_base, "bin", 3) == 0) {
oct_to_bin(number);
} else if (strncmp(to_base, "dec", 3) == 0) {
oct_to_dec(number);
} else if (strncmp(to_base, "hex", 3) == 0) {
oct_to_hex(number);
}
} else if (strncmp(from_base, "dec", 3) == 0) {
if (strlen(number) > 3 || atoi(number) > 255 || atoi(number) < 0) {
printf("based: Decimal number must be 3 or less than 3 digits and must be between 0 and 255.\n");
return 1;
}
if (strncmp(to_base, "bin", 3) == 0) {
dec_to_bin(number);
} else if (strncmp(to_base, "oct", 3) == 0) {
dec_to_oct(number);
} else if (strncmp(to_base, "hex", 3) == 0) {
dec_to_hex(number);
}
} else if (strncmp(from_base, "hex", 3) == 0) {
if (strlen(number) != 2) {
printf("based: Hexadecimal number must be 2 digits.\n");
return 1;
}
if (strncmp(to_base, "bin", 3) == 0) {
hex_to_bin(number);
} else if (strncmp(to_base, "oct", 3) == 0) {
hex_to_oct(number);
} else if (strncmp(to_base, "dec", 3) == 0) {
hex_to_dec(number);
}
}
return 0;
}

15
config.h Normal file
View file

@ -0,0 +1,15 @@
static const char *log_file_path = "sfb.log";
/* For connection */
static const int port = 5222; /* 8433 880 */
/* Length of paste's random ID */
static const int id_len = 4;
/* Max size for paste */
static const int max_file_size = 52428800; /* 50 MB */
/* Dir to store paste */
static const char *output_dir = "code";
/* URL in output */
static const char *url = "https://bin.night0721.xyz";
/* Address to listen for connection */
static const char *listen_addr = "0.0.0.0";
/* Domain for client to connect */
static const char *domain = "bin.night0721.xyz";

90
fbc.c Normal file
View file

@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include "config.h"
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s <file_path>\n", argv[0]);
exit(EXIT_FAILURE);
}
FILE *file = fopen(argv[1], "rb");
if (!file) {
perror("fopen");
exit(EXIT_FAILURE);
}
/* Determine file size */
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
rewind(file);
char *buffer = malloc(file_size);
if (!buffer) {
perror("malloc");
fclose(file);
exit(EXIT_FAILURE);
}
size_t bytes_read = fread(buffer, 1, file_size, file);
if (bytes_read != file_size) {
perror("fread");
free(buffer);
fclose(file);
exit(EXIT_FAILURE);
}
fclose(file);
struct sockaddr_in addr;
char response[512];
/* Resolve domain to IP */
struct hostent *server = gethostbyname(domain);
if (server == NULL) {
fprintf(stderr, "No such host %s", domain);
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
memcpy(&addr.sin_addr.s_addr, server->h_addr, server->h_length);
if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("connect");
close(sockfd);
exit(EXIT_FAILURE);
}
if (send(sockfd, buffer, file_size, 0) < 0) {
perror("send");
free(buffer);
close(sockfd);
exit(EXIT_FAILURE);
}
free(buffer);
memset(response, 0, sizeof(response));
ssize_t bytes_received = recv(sockfd, response, sizeof(response) - 1, 0);
if (bytes_received < 0) {
perror("recv");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("%s", response);
close(sockfd);
return 0;
}

87
index.html Normal file
View file

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sfb</title>
<style>
html {
color-scheme: dark;
}
body {
font-family: Arial, sans-serif;
color: #d7d4cf;
background-color: rgb(30, 33, 34);
}
textarea {
width: 100%;
height: 200px;
margin-bottom: 1rem;
}
button {
padding: 0.5rem 1rem;
font-size: 1rem;
}
.output {
font-family: monospace;
}
code {
display: block;
background: #f4f4f4;
padding: 0.5rem;
border: 1px solid #ddd;
margin: 1rem 0;
white-space: pre-wrap;
}
body > * {
border-color: rgb(58, 62, 65);
background-color: rgb(30, 33, 34);
}
</style>
</head>
<body>
<pre>Suckless File Bin</pre>
<pre>================</pre>
<pre></pre>
<pre>Temporary file hoster.</pre>
<pre>You can either enter text below and click submit to create a link or use CURL/other http client to send POST request for creating links</pre>
<pre>CURL example:</pre>
<code>curl -F'file=@yourfile.png' https://bin.night0721.xyz</code>
<pre>Server will responde with a URL to your file, e.g. https://bin.night0721.xyz/abcd</pre>
<textarea id="pasteContent" placeholder="Type or paste your content here..."></textarea>
<button onclick="submitPaste()">Submit</button>
<pre id="output" class="output" style="display: none;"></pre>
<script>
async function submitPaste() {
const content = document.getElementById('pasteContent').value.trim();
if (!content) {
alert('Please enter some content.');
return;
}
try {
const response = await fetch('https://bin.night0721.xyz', {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: content
});
if (!response.ok) {
throw new Error(`Server responded with status: ${response.status}`);
}
const result = await response.text();
const output = document.getElementById('output');
output.style.display = 'block';
output.innerHTML = `File URL: <a href="${result}" target="_blank">${result}</a>`;
} catch (error) {
alert('Error: ' + error.message);
}
}
</script>
</body></html>

32
nginx.conf Normal file
View file

@ -0,0 +1,32 @@
# HTTP
server {
server_name bin.night0721.xyz;
listen 80;
listen [::]:80;
location / {
proxy_pass http://127.0.0.1:9999;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 512M;
}
}
# SFP
server {
server_name bin.night0721.xyz;
listen 80;
listen [::]:80;
charset utf-8;
location / {
root /home/night/code/;
index index.txt index.html;
}
}

266
sfb.c Normal file
View file

@ -0,0 +1,266 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "config.h"
/* For slug generation */
const char *symbols = "abcdefghijklmnopqrstuvwxyz0123456789";
/* Permission for directories */
const int permission = S_IRWXU | S_IRGRP | S_IROTH | S_IXOTH | S_IXGRP;
typedef struct {
int socket;
struct sockaddr_in address;
} connection;
void
die(char *err)
{
fprintf(stderr, "%s\n", err);
exit(1);
}
static void
error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
printf("[ERROR] ");
vprintf(fmt, args);
printf("\n");
va_end(args);
}
static void
status(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
printf("[LOG] ");
vprintf(fmt, args);
printf("\n");
va_end(args);
}
/*
* Create string with current date and time
*/
static void
get_date(char *buf)
{
time_t cur_time = time(NULL);
/* Save data to provided buffer */
if (ctime_r(&cur_time, buf) == NULL) {
/* Couldn't get date, set first byte to 0 so it won't be displayed */
buf[0] = 0;
return;
}
/* Remove additional new line */
buf[strlen(buf) - 1] = 0;
}
static void
save_entry(const char *ip, const char *hostname, const char *id)
{
FILE *f = fopen(log_file_path, "a");
if (!f) {
error("Error opening log file");
return;
}
char date[26];
get_date(date);
/* Write request to file */
fprintf(f, "[%s] [%s] [%s] [%s]\n", date, ip, hostname, id);
fclose(f);
}
static void *
handle_connection(void *args)
{
connection *c = (connection *) args;
/* Get client's IP */
const char *ip = inet_ntoa(c->address.sin_addr);
/* Get client's hostname */
char hostname[512];
if (getnameinfo((struct sockaddr *)&c->address, sizeof(c->address),
hostname, sizeof(hostname), NULL, 0, 0) != 0 ) {
/* Couldn't resolve a hostname */
strcpy(hostname, "N/A");
}
char date[26];
get_date(date);
status("[%s] [%s] [%s]: New connection", date, ip, hostname);
uint8_t *buffer = malloc(max_file_size);
if (!buffer) {
error("Error allocating memory");
goto quit;
}
memset(buffer, 0, max_file_size);
const int r = recv(c->socket, buffer, max_file_size, 0);
if (r <= 0) {
/* TODO: log unsuccessful and rejected connections */
error("No data received from the client");
goto quit;
} else {
buffer[r] = 0;
/* TODO: Check if requested was performed with a known protocol */
/* Generate id */
char id[id_len + 1];
for (int i = 0; i < id_len; i++) {
int n = rand() % strlen(symbols);
id[i] = symbols[n];
}
id[id_len] = 0;
/* 1 for slash and 1 for null */
size_t len = strlen(output_dir) + id_len + 2;
/* Create path */
char path[len];
snprintf(path, len, "%s/%s", output_dir, id);
/* Try create directory for paste */
if (mkdir(path, permission) != 0) {
error("Error creating directory for paste");
goto quit;
}
/* Save to file */
const char *file_name = "index.txt";
len += strlen(file_name) + 1;
/* Construct path */
char paste_path[len];
snprintf(paste_path, len, "%s/%s", path, file_name);
/* Save file */
FILE *f = fopen(paste_path, "w");
if (!f) {
goto quit;
}
if (fprintf(f, "%s", buffer) < 0) {
fclose(f);
goto quit;
}
fclose(f);
/* Write a response to the user */
const size_t url_len = strlen(url) + id_len + 3;
char full_url[url_len];
snprintf(full_url, url_len, "%s/%s\n", url, id);
/* Send the response */
write(c->socket, full_url, url_len);
status("[%s] [%s] [%s]: Received %d bytes, saved to %s", date, ip, hostname, r, id);
save_entry(ip, hostname, id);
goto quit;
}
quit:
free(buffer);
close(c->socket);
free(c);
pthread_exit(NULL);
return NULL;
}
int
main(void)
{
srand(time(NULL));
mkdir(output_dir, permission);
if (access(output_dir, W_OK) != 0) {
error("Output directory is not writable");
return -1;
}
FILE *f = fopen(log_file_path, "a+");
if (!f) {
die("Cannot open log file");
}
fclose(f);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
/* Reuse address */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1} , sizeof(int)) < 0) {
perror("setsockopt");
return -1;
}
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(listen_addr);
address.sin_port = htons(port);
if (bind(fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
perror("bind");
return -1;
}
if (listen(fd, 128) != 0) {
perror("listen");
return -1;
}
status("spb listening on %s:%d", listen_addr, port);
while (1) {
/* Create a thread for each connection */
struct sockaddr_in address;
socklen_t addlen = sizeof(address);
/* Get client fd */
int s = accept(fd, (struct sockaddr *) &address, &addlen);
if (s < 0) {
error("Error on accepting connection!");
continue;
}
connection *c = malloc(sizeof(connection));
if (!c) {
die("Error allocating memory");
}
c->socket = s;
c->address = address;
pthread_t id;
if (pthread_create(&id, NULL, &handle_connection, c) != 0) {
error("Error spawning thread");
continue;
}
pthread_detach(id);
}
return 0;
}

121
sfb.py Normal file
View file

@ -0,0 +1,121 @@
from flask import Flask, request, jsonify, send_from_directory, send_file, render_template_string
from flask_cors import CORS, cross_origin
import os
import random
import string
from datetime import datetime
from pygments import highlight
from pygments.lexers import guess_lexer
from pygments.formatters import HtmlFormatter
# Configuration
OUTPUT_DIR = "code"
LOG_FILE = "spb.log"
SYMBOLS = string.ascii_lowercase + string.ascii_uppercase + string.digits
ID_LEN = 4
PORT = 9999
URL = f"https://bin.night0721.xyz"
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
os.makedirs(OUTPUT_DIR, exist_ok=True)
def generate_id():
return ''.join(random.choices(SYMBOLS, k=ID_LEN))
def log_request(ip, hostname, unique_id):
"""Log the request details."""
timestamp = datetime.now().ctime()
with open(LOG_FILE, 'a') as log_file:
fmtstr = f"[{timestamp}] [{ip}] [{hostname}] [{unique_id}]"
print(fmtstr)
log_file.write(fmtstr + "\n")
@app.route('/', methods=['POST'])
@cross_origin()
def upload():
try:
id = generate_id()
if 'file' in request.files:
file = request.files['file']
if file.filename == '':
return jsonify({"error": "No file selected"}), 400
filename = id
file.save(os.path.join(OUTPUT_DIR, filename))
else:
data = request.data.decode('utf-8')
if not data:
return jsonify({"error": "No data provided"}), 400
filename = os.path.join(OUTPUT_DIR, id)
with open(filename, 'w') as f:
f.write(data)
f.write("\n")
f.close()
# IP Hostname
log_request(request.remote_addr, request.host, filename)
return f"{URL}/{id}\n"
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/', methods=['GET'])
@cross_origin()
def index():
return send_from_directory('.', 'index.html')
@app.route("/<id>", methods=["GET"])
def get_file(id):
file_path = os.path.join(OUTPUT_DIR, id)
if not os.path.isfile(file_path):
return jsonify({"error": f"File '{id}' not found"}), 404
try:
# Send the file content
return send_file(file_path, as_attachment=False)
except Exception as e:
return jsonify({"error": str(e)}), 500
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
{{ style }}
</style>
</head>
<body>
<pre>{{ content|safe }}</pre>
</body>
</html>
"""
@app.route("/<id>/raw", methods=["GET"])
def get_file_raw(id):
file_path = os.path.join(OUTPUT_DIR, id)
if not os.path.isfile(file_path):
return jsonify({"error": f"File '{id}' not found"}), 404
try:
with open(file_path, 'r') as file:
content = file.read()
lexer = guess_lexer(content)
formatter = HtmlFormatter()
highlighted_content = highlight(content, lexer, formatter)
style = formatter.get_style_defs()
return render_template_string(
HTML_TEMPLATE,
id=id,
content=highlighted_content,
style=style,
)
except Exception as e:
return jsonify({"error": str(e)}), 500
app.run(host="0.0.0.0", port=PORT, debug=False)