Pinnwand: Updated handling of binary files

Reworked for better handling of binary files. Added an option to list valid expiry times.
This commit is contained in:
Forza 2025-01-12 12:38:58 +01:00
parent e33259fdc3
commit d53eb53fea

View File

@ -1,15 +1,35 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0-or-later
###
# Paste to a Pinnwand pastebin service
#
# This script uploads text content from files or stdin to a Pinnwand
# pastebin instance. It supports specifying expiry times, lexers for
# syntax highlighting.
#
# Features:
# - Upload content from files or stdin
# - Specify expiry times and lexers for syntax highlighting
# - Supports autodetection (if enabled by the server) or explicit
# lexer selection
#
# Dependencies:
# - curl: For sending HTTP requests to the Pinnwand API
# - jq: For parsing JSON responses and encoding input
# - file: For binary file detection
#
# SPDX-License-Identifier: CC0-1.0
###
# Base URL of the Pinnwand instance
PINNWAND_BASE_URL="https://gist.tnonline.net/api/v1"
PINNWAND_BASE_URL="${PINNWAND_BASE_URL:-https://gist.tnonline.net/api/v1}"
PASTE_URL="${PINNWAND_BASE_URL}/paste"
LEXER_URL="${PINNWAND_BASE_URL}/lexer"
# Default options
expiry="1day"
lexer="text"
lexer="autodetect"
# Function to show help information
show_help() {
@ -19,10 +39,13 @@ show_help() {
Usage: $s [options] [file1 file2 ...]
Options:
-e, --expiry <expiry> Set the expiry time for the paste (e.g., 1day, 1hour).
Default is '1day' if not specified.
-e, --expiry <expiry> Set the expiry time for the paste (e.g., 1day,
1hour). Default is '1day' if not specified.
--expiries List valid expiry periods.
-l, --lexer <lexer> Specify the lexer to use for syntax highlighting.
--lexers List all available lexers in 'name : description' format.
Default is 'autodetect' if not specified.
--lexers List all available lexers in 'name : description'
format.
-h, --help Show this help message and exit.
Examples:
@ -33,18 +56,13 @@ END
exit 0
}
# Function to check if a file or input is binary
is_binary() {
local input="$1"
if [[ -f "$input" ]]; then
# If input is a file, check directly with file command
[[ "$(file --mime-encoding -b -L "$input")" == "binary" ]]
else
# If input is from stdin, use grep to check for binary content
grep -qI . <<< "$input"
return $? # Return 0 for text, non-zero for binary
fi
# Use the `file` command to check if the input is binary
[[ "$(file --mime-encoding -b -L "$input")" == "binary" ]]
}
# Function to post content to Pinnwand
@ -53,7 +71,14 @@ post_to_pinnwand() {
local lexer="$2"
shift 2
local files=("$@")
# Create temporary files for payload and response
tmp_payload=$(mktemp 2>/dev/null) || { echo "Error: Failed to create a temporary file for payload"; exit 1; }
tmp_response=$(mktemp 2>/dev/null) || { echo "Error: Failed to create a temporary file for response"; rm -f "$tmp_payload"; exit 1; }
tmp_status=$(mktemp 2>/dev/null) || { echo "Error: Failed to create a temporary file for status code"; rm -f "$tmp_payload" "$tmp_response"; exit 1; }
tmp_stdin=$(mktemp 2>/dev/null) || { echo "Error: Failed to create a temporary file for stdin"; rm -f "$tmp_payload" "$tmp_response" "$tmp_status"; exit 1; }
trap 'rm -f "$tmp_payload" "$tmp_response" "$tmp_status" "$tmp_stdin"' EXIT
# Prepare files array for JSON
files_json="["
@ -61,13 +86,12 @@ post_to_pinnwand() {
# Add each file to the JSON array
for file in "${files[@]}"; do
if [[ -f "$file" ]]; then
# Check if the file is binary
if is_binary "$file"; then
echo "Error: $file is a binary file. Only text files are allowed."
exit 1
fi
content=$(<"$file" jq -Rs .) # Read and JSON-encode file content
files_json+="{\"name\":\"$(basename "$file")\",\"lexer\":\"$lexer\",\"content\":$content},"
else
@ -76,31 +100,55 @@ post_to_pinnwand() {
fi
done
else
# If no files were provided, read from stdin
stdin_content=$(cat | jq -Rs .) # Read and JSON-encode stdin content
# Write stdin to a temp file
cat > "$tmp_stdin"
# Check if stdin content is binary
if is_binary "$stdin_content"; then
if is_binary "$tmp_stdin"; then
echo "Error: Input from stdin is binary. Only text content is allowed."
exit 1
fi
# Read and JSON-encode stdin content
stdin_content=$(<"$tmp_stdin" jq -Rs .)
files_json+="{\"name\":\"stdin\",\"lexer\":\"$lexer\",\"content\":$stdin_content},"
fi
# Remove trailing comma and close array
files_json="${files_json%,}]"
response=$(curl -s -X POST "$PASTE_URL" \
-H "Content-Type: application/json" \
-d '{"expiry":"'"$expiry"'","files":'"$files_json"'}' )
echo '{"expiry":"'"$expiry"'","files":'"$files_json"'}' > "$tmp_payload"
# Send the payload using curl and save the response and HTTP status separately
curl -s -o "$tmp_response" -w "%{http_code}" -X POST "$PASTE_URL" \
-H "Content-Type: application/json" --data @"$tmp_payload" > "$tmp_status"
# Extract link and removal URLs from the response
link=$(echo "$response" | jq -r '.link')
removal=$(echo "$response" | jq -r '.removal')
# Extract HTTP status code and response body
http_code=$(<"$tmp_status")
response_body=$(<"$tmp_response")
# Check if the response contains a URL
if [[ "$response" == null ]]; then
echo "Error: Could not create paste"
# Ensure http_code is a valid number
if ! [[ "$http_code" =~ ^[0-9]{3}$ ]]; then
echo "Error: Failed to parse HTTP status code. Raw response:"
cat "$tmp_response"
exit 1
fi
# Check if the HTTP status code indicates success
if [[ "$http_code" -ne 200 ]]; then
echo "Error: Failed to create paste (HTTP $http_code). Response body:"
echo "$response_body"
exit 1
fi
# Extract link and removal URLs from the response body
link=$(echo "$response_body" | jq -r '.link')
removal=$(echo "$response_body" | jq -r '.removal')
# Check if the response contains valid URLs
if [[ -z "$link" || "$link" == "null" ]]; then
echo "Error: Could not create paste. API response:"
echo "$response_body"
exit 1
else
echo "Paste URL: $link"
@ -108,6 +156,22 @@ post_to_pinnwand() {
fi
}
# Function to fetch and list available expiry times
list_expiries() {
local expiries
# Fetch expiry options from the API
expiries=$(curl -s "$PINNWAND_BASE_URL/expiry" | jq -r 'keys_unsorted | join(" ")' 2>/dev/null)
if [[ -z "$expiries" ]]; then
echo "Error: Unable to fetch valid expiry options from the server."
exit 1
fi
echo "Valid expiry times: $expiries"
exit 0
}
# Function to list available lexers
list_lexers() {
curl -s "$LEXER_URL" | jq -r '.'
@ -118,16 +182,27 @@ list_lexers() {
while [ "$#" -gt 0 ]; do
case $1 in
-e|--expiry)
if [[ -z "$2" || "$2" == -* ]]; then
echo "Error: The --expiry option requires a value."
exit 1
fi
expiry="$2"
shift 2
;;
-l|--lexer)
if [[ -z "$2" || "$2" == -* ]]; then
echo "Error: The --lexer option requires a value."
exit 1
fi
lexer="$2"
shift 2
;;
--lexers)
list_lexers
;;
--expiries)
list_expiries
;;
-h|--help)
show_help
;;
@ -142,3 +217,4 @@ files=("$@")
# Post content from provided files or stdin
post_to_pinnwand "$expiry" "$lexer" "${files[@]}"