Merge pull request #208 from schlagmichdoch/enable-multiple-files-cli

Enable sending multiple files via cli
This commit is contained in:
schlagmichdoch 2023-12-11 19:13:49 +01:00 committed by GitHub
commit dcdc9a5269
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 414 additions and 338 deletions

View file

@ -1,3 +1,14 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
# Build a Docker image whenever it is pushed to master
name: Docker Image CI name: Docker Image CI
on: on:
@ -13,6 +24,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Build the Docker image - name: Build the Docker image
run: docker build --pull . -f Dockerfile -t pairdrop run: docker build --pull . -f Dockerfile -t pairdrop

View file

@ -7,6 +7,8 @@
# To get a newer version, you will need to update the SHA. # To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning. # You can also reference a tag or branch, but the action may change without warning.
# Create a Docker image and push it to ghcr.io whenever a new version tag is pushed
name: GHCR Image CI name: GHCR Image CI
on: on:
@ -27,16 +29,16 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup qemu - name: Setup qemu
uses: docker/setup-qemu-action@v2.1.0 uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
- name: Setup Docker Buildx - name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2.5.0 uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
@ -44,12 +46,12 @@ jobs:
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4 # v5.3.0
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64

35
.github/workflows/zip-release.yml vendored Normal file
View file

@ -0,0 +1,35 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
# Create a new zip file from pairdrop-cli whenever a new version tag is pushed
name: Zip Release
on:
push:
tags:
- "v*.*.*"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Archive Release
uses: thedoctor0/zip-release@b57d897cb5d60cb78b51a507f63fa184cfe35554 # v0.7.6
with:
type: 'zip'
filename: 'pairdrop-cli.zip'
path: 'pairdrop-cli'
exclusions: '*.git* /*node_modules/* .editorconfig'
- name: Upload Release
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0
with:
artifacts: "pairdrop-cli.zip"
token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -67,10 +67,11 @@ Developed based on [Snapdrop](https://github.com/RobinLinus/snapdrop)
* Multiple files are transferred at once with an overall progress indicator * Multiple files are transferred at once with an overall progress indicator
### Send Files or Text Directly From Share Menu, Context Menu or CLI ### Send Files or Text Directly From Share Menu, Context Menu or CLI
* [Send files directly from context menu on Windows](/docs/how-to.md#send-files-directly-from-context-menu-on-windows) * [Send files directly from context menu on Windows](/docs/how-to.md#send-multiple-files-and-directories-directly-from-context-menu-on-windows)
* [Send directly from share menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios) * [Send files directly from context menu on Ubuntu (using Nautilus)](/docs/how-to.md#send-multiple-files-and-directories-directly-from-context-menu-on-ubuntu-using-nautilus)
* [Send directly from share menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android) * [Send files directly from share menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios)
* [Send directly via command-line interface](/docs/how-to.md#send-directly-via-command-line-interface) * [Send files directly from share menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android)
* [Send files directly via command-line interface](/docs/how-to.md#send-directly-via-command-line-interface)
### Other changes ### Other changes
* Change your display name permanently to easily differentiate your devices * Change your display name permanently to easily differentiate your devices

View file

@ -1,84 +1,120 @@
# How-To # How-To
## Send files directly from context menu on Windows
### Registering to open files with PairDrop
The [File Handling API](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files) is implemented
This is still experimental and must be enabled via a flag **before** the PWA is installed to Windows.
1. [Enabled feature in Edge](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files#enable-the-file-handling-api)
2. Install PairDrop by visiting https://pairdrop.net/ with the Edge web browser and install it as described [here](faq.md#help--i-cant-install-the-pwa-).
3. You are done! You can now send most files one at a time via PairDrop:
_context menu > Open with > PairDrop_
[//]: # (Todo: add screenshots)
### Sending multiple files to PairDrop
Outstandingly, it is also possible to send multiple files to PairDrop \
via the context menu by adding PairDrop to the `Send to` menu:
1. [Register PairDrop as file handler](#registering-to-open-files-with-pairdrop)
2. Hit Windows Key+R, type: `shell:programs` and hit Enter.
3. Copy the PairDrop shortcut from the directory
4. Hit Windows Key+R, type: `shell:sendto` and hit Enter.
5. Paste the copied shortcut into the directory
6. You are done! You can now send multiple files (but no directories) directly via PairDrop:
_context menu > Send to > PairDrop_
[//]: # (Todo: add screenshots)
## Send directly from share menu on iOS ## Send directly from share menu on iOS
I created an iOS shortcut to send images, files, folder, URLs \ I created an iOS shortcut to send images, files, folder, URLs \
or text directly from the share-menu or text directly from the share-menu
https://routinehub.co/shortcut/13990/ https://routinehub.co/shortcut/13990/
[//]: # (Todo: add doku with screenshots) [//]: # (Todo: Add screenshots)
<br>
## Send directly from share menu on Android ## Send directly from share menu on Android
The [Web Share Target API](https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target) is implemented. The [Web Share Target API](https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target) is implemented.
When the PWA is installed, it will register itself to the share-menu of the device automatically. When the PWA is installed, it will register itself to the share-menu of the device automatically.
<br>
## Send directly via command-line interface ## Send directly via command-line interface
Send files or text with PairDrop via command-line interface. Send files or text with PairDrop via command-line interface. \
This opens PairDrop in the default browser where you can choose the receiver. This opens PairDrop in the default browser where you can choose the receiver.
### Usage ### Usage
```bash ```bash
$ pairdrop -h pairdrop -h
Current domain: https://pairdrop.net/ ```
```bash
Send files or text with PairDrop via command-line interface.
Current domain: https://pairdrop-dev.onrender.com/
Usage: Usage:
Open PairDrop: pairdrop Open PairDrop: pairdrop
Send files: pairdrop file/directory Send files: pairdrop file1/directory1 (file2/directory2 file3/directory3 ...)
Send text: pairdrop -t "text" Send text: pairdrop -t "text"
Specify domain: pairdrop -d "https://pairdrop.net/" Specify domain: pairdrop -d "https://pairdrop.net/"
Show this help text: pairdrop (-h|--help) Show this help text: pairdrop (-h|--help)
This pairdrop-cli version was released alongside v1.10.0
``` ```
On Windows Command Prompt you need to use bash: `bash pairdrop -h` <br>
### Setup ### Setup
Download the bash file: [pairdrop-cli/pairdrop](/pairdrop-cli/pairdrop). Download the bash file: [pairdrop-cli/pairdrop](/pairdrop-cli/pairdrop).
#### Linux #### Linux
1. Put the file in a preferred folder e.g. `/usr/local/bin` 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases)
2. Make sure the bash file is executable. Otherwise, use `chmod +x pairdrop` 2. Unzip the archive to a folder of your choice e.g. `/usr/local/bin/pairdrop-cli/`
3. Add absolute path of the folder to PATH variable to make `pairdrop` available globally by executing 3. Make sure the bash file `/usr/local/bin/pairdrop-cli/pairdrop` is executable. Otherwise, use `chmod +x pairdrop`
`export PATH=$PATH:/opt/pairdrop-cli` 4. Add absolute path of the folder to PATH variable to make `pairdrop` available globally by executing
`export PATH=$PATH:/usr/local/bin/pairdrop-cli/`
<br>
#### Mac #### Mac
1. add bash file to `/usr/local/bin` 1. add bash file to `/usr/local/bin`
<br>
#### Windows #### Windows
1. Put file in a preferred folder e.g. `C:\Users\Public\pairdrop-cli` 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases)
2. Search for and open `Edit environment variables for your account` 2. Put file in a preferred folder e.g. `C:\Program Files\pairdrop-cli`
3. Click `Environment Variables…` 3. Search for and open `Edit environment variables for your account`
4. Under *System Variables* select `Path` and click *Edit...* 4. Click `Environment Variables…`
5. Click *New*, insert the preferred folder (`C:\Users\Public\pairdrop-cli`), click *OK* until all windows are closed 5. Under *System Variables* select `Path` and click *Edit...*
6. Reopen Command prompt window 6. Click *New*, insert the preferred folder (`C:\Program Files\pairdrop-cli`), click *OK* until all windows are closed
7. Reopen Command prompt window
<br>
### Requirements
As Windows cannot execute bash scripts natively, you need to install [Git Bash](https://gitforwindows.org/).
Then, you can also use pairdrop-cli from the default Windows Command Prompt \
by using the shell file instead of the bash file: `pairdrop.sh -h` which then itself executes \
pairdrop-cli (the bash file) via the Git Bash.
<br>
## Send multiple files and directories directly from context menu on Windows
### Registering to open files with PairDrop
It is possible to send multiple files with PairDrop via the context menu by adding pairdrop-cli to Windows `Send to` menu:
1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases)
2. Unzip the archive to a folder of your choice e.g. `C:\Program Files\pairdrop-cli\`
3. Copy the shortcut _send with PairDrop.lnk_
4. Hit Windows Key+R, type: `shell:sendto` and hit Enter.
5. Paste the copied shortcut into the directory
6. Open the properties window of the shortcut and edit the link field to point to _send-with-pairdrop.ps1_ located in the folder you used in step 2: \
`"C:\Program Files\PowerShell\7\pwsh.exe" -File "C:\Program Files\pairdrop-cli\send-with-pairdrop.ps1"`
7. You are done! You can now send multiple files and directories directly via PairDrop:
> _context menu > Send to > PairDrop_
##### Requirements
As Windows cannot execute bash scripts natively, you need to install [Git Bash](https://gitforwindows.org/).
<br>
## Send multiple files and directories directly from context menu on Ubuntu using Nautilus
### Registering to open files with PairDrop
It is possible to send multiple files with PairDrop via the context menu by adding pairdrop-cli to Nautilus `Scripts` menu:
1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases)
2. Unzip the archive to a folder of your choice e.g. `/usr/local/bin/pairdrop-cli/`
3. Copy the shell file _send-with-pairdrop.sh_ to `/home/<user>/.local/share/nautilus/scripts/`
4. Edit the shell file and edit the variable `pathToPairDropCli` to point to the pairdrop-cli executable from step 2 (e.g. `/usr/local/bin/pairdrop-cli/pairdrop`)
5. Make sure the shell file `/home/<user>/.local/share/nautilus/scripts/send-with-pairdrop.sh` is executable. Otherwise, use `chmod +x send-with-pairdrop.sh`
6. You are done! You can now send multiple files and directories directly via PairDrop:
> _context menu > Scripts > send-with-pairdrop.sh_
<br>
## File Handling API
The [File Handling API](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files)
was implemented, but it was removed as default file associations were overwritten ([#17](https://github.com/schlagmichdoch/PairDrop/issues/17),
[#116](https://github.com/schlagmichdoch/PairDrop/issues/116) [#190](https://github.com/schlagmichdoch/PairDrop/issues/190))
and it only worked with explicitly specified file types and not with directories at all.
[< Back](/README.md) [< Back](/README.md)

1
pairdrop-cli/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.pairdrop-cli-config

View file

@ -12,10 +12,12 @@ help()
echo echo
echo "Usage:" echo "Usage:"
echo -e "Open PairDrop:\t\t$(basename "$0")" echo -e "Open PairDrop:\t\t$(basename "$0")"
echo -e "Send files:\t\t$(basename "$0") file/directory" echo -e "Send files:\t\t$(basename "$0") file1/directory1 (file2/directory2 file3/directory3 ...)"
echo -e "Send text:\t\t$(basename "$0") -t \"text\"" echo -e "Send text:\t\t$(basename "$0") -t \"text\""
echo -e "Specify domain:\t\t$(basename "$0") -d \"https://pairdrop.net/\"" echo -e "Specify domain:\t\t$(basename "$0") -d \"https://pairdrop.net/\""
echo -e "Show this help text:\t$(basename "$0") (-h|--help)" echo -e "Show this help text:\t$(basename "$0") (-h|--help)"
echo
echo "This pairdrop-cli version was released alongside v1.10.0"
} }
openPairDrop() openPairDrop()
@ -36,7 +38,7 @@ openPairDrop()
elif [[ $OS == "WSL" || $OS == "WSL2" ]];then elif [[ $OS == "WSL" || $OS == "WSL2" ]];then
powershell.exe /c "Start-Process ${url}" powershell.exe /c "Start-Process ${url}"
else else
xdg-open "$url" xdg-open "$url" > /dev/null 2>&1
fi fi
@ -62,7 +64,7 @@ setOs()
specifyDomain() specifyDomain()
{ {
[[ ! $1 = http* ]] || [[ ! $1 = */ ]] && echo "Incorrect format. Specify domain like https://pairdrop.net/" && exit [[ ! $1 = http* ]] || [[ ! $1 = */ ]] && echo "Incorrect format. Specify domain like https://pairdrop.net/" && exit
echo "DOMAIN=${1}" > "$CONFIGPATH" echo "DOMAIN=${1}" > "$config_path"
echo -e "Domain is now set to:\n$1\n" echo -e "Domain is now set to:\n$1\n"
} }
@ -87,75 +89,228 @@ sendText()
exit exit
} }
escapePSPath()
{
local path=$1
# escape '[' and ']' with grave accent (`) character
pathPS=${path//[/\`[}
pathPS=${pathPS//]/\`]}
# escape single quote (') with another single quote (')
pathPS=${pathPS//\'/\'\'}
# Convert GitHub bash path "/i/path" to Windows path "I:/path"
if [[ $pathPS == /* ]]; then
# Remove preceding slash
pathPS="${pathPS#/}"
# Convert drive letter to uppercase
driveLetter=$(echo "${pathPS::1}" | tr '[:lower:]' '[:upper:]')
# Put together absolute path as used in Windows
pathPS="${driveLetter}:${pathPS:1}"
fi
echo "$pathPS"
}
sendFiles() sendFiles()
{ {
params="base64zip=hash" params="base64zip=hash"
if [[ $1 == */ ]]; then workingDir="$(pwd)"
path="${1::-1}" tmpDir="/tmp/pairdrop-cli-temp/"
else tmpDirPS="\$env:TEMP/pairdrop-cli-temp/"
path=$1
fi index=0
zipPath="${path}_pairdrop.zip" directoryBaseNamesUnix=()
zipPath=${zipPath// /_} directoryPathsUnix=()
filePathsUnix=()
directoryCount=0
fileCount=0
pathsPS=""
[[ -a "$zipPath" ]] && echo "Cannot overwrite $zipPath. Please remove first." && exit #create tmp folder if it does not exist already
if [[ ! -d "$tmpDir" ]]; then
if [[ -d $path ]]; then mkdir "$tmpDir"
zipPathTemp="${path}_pairdrop_temp.zip"
[[ -a "$zipPathTemp" ]] && echo "Cannot overwrite $zipPathTemp. Please remove first." && exit
echo "Processing directory..."
# Create zip files temporarily to send directory
if [[ $OS == "Windows" ]];then
powershell.exe -Command "Compress-Archive -Path ${path} -DestinationPath ${zipPath}"
echo "Compress-Archive -Path ${zipPath} -DestinationPath ${zipPathTemp}"
powershell.exe -Command "Compress-Archive -Path ${zipPath} -DestinationPath ${zipPathTemp}"
else
zip -q -b /tmp/ -r "$zipPath" "$path"
zip -q -b /tmp/ "$zipPathTemp" "$zipPath"
fi
if [[ $OS == "Mac" ]];then
hash=$(base64 -i "$zipPathTemp")
else
hash=$(base64 -w 0 "$zipPathTemp")
fi
# remove temporary temp file
rm "$zipPathTemp"
else
echo "Processing file..."
# Create zip file temporarily to send file
if [[ $OS == "Windows" ]];then
powershell.exe -Command "Compress-Archive -Path ${path} -DestinationPath ${zipPath} -CompressionLevel Optimal"
else
zip -q -b /tmp/ "$zipPath" "$path"
fi
if [[ $OS == "Mac" ]];then
hash=$(base64 -i "$zipPath")
else
hash=$(base64 -w 0 "$zipPath")
fi
fi fi
# remove temporary temp file for arg in "$@"; do
rm "$zipPath" echo "$arg"
[[ ! -e "$arg" ]] && echo "The given path $arg does not exist." && exit
if [[ $(echo -n "$hash" | wc -m) -gt 32600 ]];then # Remove trailing slash from directory
arg="${arg%/}"
# get absolute path and basename of file/directory
absolutePath=$(realpath "$arg")
baseName=$(basename "$absolutePath")
directoryPath=$(dirname "$absolutePath")
if [[ -d $absolutePath ]]; then
# is directory
((directoryCount+=1))
# add basename and directory path to arrays
directoryBaseNamesUnix+=("$baseName")
directoryPathsUnix+=("$directoryPath")
else
# is file
((fileCount+=1))
absolutePathUnix=$absolutePath
# append new path and separate paths with space
filePathsUnix+=("$absolutePathUnix")
fi
# Prepare paths for PowerShell on Windows
if [[ $OS == "Windows" ]];then
absolutePathPS=$(escapePSPath "$absolutePath")
# append new path and separate paths with commas
pathsPS+="'${absolutePathPS}', "
fi
# set fileNames on first loop
if [[ $index == 0 ]]; then
baseNameU=${baseName// /_}
# Prevent baseNameU being empty for hidden files by removing the preceding dot
if [[ $baseNameU == .* ]]; then
baseNameU=${baseNameU#.*}
fi
# only use trunk of basename "document.txt" -> "document"
baseNameTrunk=${baseNameU%.*}
# remove all special characters
zipName=${baseNameTrunk//[^a-zA-Z0-9_]/}
zipToSendAbs="${tmpDir}${zipName}_pairdrop.zip"
wrapperZipAbs="${tmpDir}${zipName}_pairdrop_wrapper.zip"
if [[ $OS == "Windows" ]];then
zipToSendAbsPS="${tmpDirPS}${zipName}_pairdrop.zip"
wrapperZipAbsPS="${tmpDirPS}${zipName}_pairdrop_wrapper.zip"
fi
fi
((index+=1)) # somehow ((index++)) stops the script
done
# Prepare paths for PowerShell on Windows
if [[ $OS == "Windows" ]];then
# remove trailing comma
pathsPS=${pathsPS%??}
fi
echo "Preparing ${fileCount} files and ${directoryCount} directories..."
# if arguments include files only -> zip files once so files it is unzipped by sending browser
# if arguments include directories -> wrap first zip in a second wrapper zip so that after unzip by sending browser a zip file is sent to receiver
#
# Preferred zip structure:
# pairdrop "d1/d2/d3/f1" "../../d4/d5/d6/f2" "d7/" "../d8/" "f5"
# zip structure: pairdrop.zip
# |-f1
# |-f2
# |-d7/
# |-d8/
# |-f5
# -> truncate (relative) paths but keep directories
[[ -e "$zipToSendAbs" ]] && echo "Cannot overwrite $zipToSendAbs. Please remove first." && exit
if [[ $OS == "Windows" ]];then
# Powershell does preferred zip structure natively
powershell.exe -Command "Compress-Archive -Path ${pathsPS} -DestinationPath ${zipToSendAbsPS}"
else
# Workaround needed to create preferred zip structure on unix systems
# Create zip file with all single files by junking the path
if [[ $fileCount != 0 ]]; then
zip -q -b /tmp/ -j -0 -r "$zipToSendAbs" "${filePathsUnix[@]}"
fi
# Add directories recursively to zip file
index=0
while [[ $index < $directoryCount ]]; do
# workaround to keep directory name but junk the rest of the paths
# cd to path above directory
cd "${directoryPathsUnix[index]}"
# add directory to zip without junking the path
zip -q -b /tmp/ -0 -u -r "$zipToSendAbs" "${directoryBaseNamesUnix[index]}"
# cd back to working directory
cd "$workingDir"
((index+=1)) # somehow ((index++)) stops the script
done
fi
# If directories are included send as zip
# -> Create additional zip wrapper which will be unzipped by the sending browser
if [[ "$directoryCount" != 0 ]]; then
echo "Bundle as ZIP file..."
# Prevent filename from being absolute zip path by "cd"ing to directory before zipping
zipToSendDirectory=$(dirname "$zipToSendAbs")
zipToSendBaseName=$(basename "$zipToSendAbs")
cd "$zipToSendDirectory"
[[ -e "$wrapperZipAbs" ]] && echo "Cannot overwrite $wrapperZipAbs. Please remove first." && exit
if [[ $OS == "Windows" ]];then
powershell.exe -Command "Compress-Archive -Path ${zipToSendBaseName} -DestinationPath ${wrapperZipAbsPS} -CompressionLevel Optimal"
else
zip -q -b /tmp/ -0 "$wrapperZipAbs" "$zipToSendBaseName"
fi
cd "$workingDir"
# remove inner zip file and set wrapper as zipToSend (do not differentiate between OS as this is done via Git Bash on Windows)
rm "$zipToSendAbs"
zipToSendAbs=$wrapperZipAbs
fi
# base64 encode zip file
if [[ $OS == "Mac" ]];then
hash=$(base64 -i "$zipToSendAbs")
else
hash=$(base64 -w 0 "$zipToSendAbs")
fi
# remove zip file (do not differentiate between OS as this is done via Git Bash on Windows)
rm "$zipToSendAbs"
if [[ $(echo -n "$hash" | wc -m) -gt 1000 ]];then
params="base64zip=paste" params="base64zip=paste"
# Copy $hash to clipboard
if [[ $OS == "Windows" || $OS == "WSL" || $OS == "WSL2" ]];then if [[ $OS == "Windows" || $OS == "WSL" || $OS == "WSL2" ]];then
echo -n "$hash" | clip.exe echo -n "$hash" | clip.exe
elif [[ $OS == "Mac" ]];then elif [[ $OS == "Mac" ]];then
echo -n "$hash" | pbcopy echo -n "$hash" | pbcopy
elif [ -n "$WAYLAND_DISPLAY" ]; then
# Wayland
if ! command -v wl-copy &> /dev/null; then
echo -e "You need to install 'wl-copy' to send bigger filePathsUnix from cli"
echo "Try: sudo apt install wl-clipboard"
exit 1
fi
# Workaround to prevent use of Pipe which has a max letter limit
echo -n "$hash" > /tmp/pairdrop-cli-temp/pairdrop_hash_temp
wl-copy < /tmp/pairdrop-cli-temp/pairdrop_hash_temp
rm /tmp/pairdrop-cli-temp/pairdrop_hash_temp
else else
(echo -n "$hash" | xclip) || echo "You need to install xclip for sending bigger files from cli" # X11
if ! command -v xclip &> /dev/null; then
echo -e "You need to install 'xclip' to send bigger filePathsUnix from cli"
echo "Try: sudo apt install xclip"
exit 1
fi
echo -n "$hash" | xclip -sel c
fi fi
hash= hash=
fi fi
openPairDrop openPairDrop
exit exit
} }
@ -165,31 +320,32 @@ sendFiles()
# Main program # # Main program #
############################################################ ############################################################
############################################################ ############################################################
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" script_path="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
pushd . > '/dev/null'; pushd . > '/dev/null';
SCRIPTPATH="${BASH_SOURCE[0]:-$0}"; script_path="${BASH_SOURCE[0]:-$0}";
while [ -h "$SCRIPTPATH" ]; while [ -h "$script_path" ];
do do
cd "$( dirname -- "$SCRIPTPATH"; )"; cd "$( dirname -- "$script_path"; )";
SCRIPTPATH="$( readlink -f -- "$SCRIPTPATH"; )"; script_path="$( readlink -f -- "$script_path"; )";
done done
cd "$( dirname -- "$SCRIPTPATH"; )" > '/dev/null'; cd "$( dirname -- "$script_path"; )" > '/dev/null';
SCRIPTPATH="$( pwd; )"; script_path="$( pwd; )";
popd > '/dev/null'; popd > '/dev/null';
CONFIGPATH="${SCRIPTPATH}/.pairdrop-cli-config" config_path="${script_path}/.pairdrop-cli-config"
[ ! -f "$CONFIGPATH" ] && [ ! -f "$config_path" ] &&
specifyDomain "https://pairdrop.net/" && specifyDomain "https://pairdrop.net/" &&
[ ! -f "$CONFIGPATH" ] && [ ! -f "$config_path" ] &&
echo "Could not create config file. Add 'DOMAIN=https://pairdrop.net/' to a file called .pairdrop-cli-config in the same file as this 'pairdrop' bash file" echo "Could not create config file. Add 'DOMAIN=https://pairdrop.net/' to a file called .pairdrop-cli-config in the same file as this 'pairdrop' bash file"
[ ! -f "$CONFIGPATH" ] || export "$(grep -v '^#' "$CONFIGPATH" | xargs)" [ ! -f "$config_path" ] || export "$(grep -v '^#' "$config_path" | xargs)"
setOs setOs
############################################################ ############################################################
# Process the input options. Add options as needed. # # Process the input options. Add options as needed. #
############################################################ ############################################################
@ -198,24 +354,23 @@ setOs
[[ $# -eq 0 ]] && openPairDrop && exit [[ $# -eq 0 ]] && openPairDrop && exit
# display help and exit if first argument is "--help" or more than 2 arguments are given # display help and exit if first argument is "--help" or more than 2 arguments are given
[ "$1" == "--help" ] || [[ $# -gt 2 ]] && help && exit [ "$1" == "--help" ] && help && exit
while getopts "d:ht:*" option; do while getopts "d:ht:*" option; do
case $option in case $option in
d) # specify domain d) # specify domain - show help and exit if too many arguments
specifyDomain "$2" [[ $# -gt 2 ]] && help && exit
exit;; specifyDomain "$2"
t) # Send text exit;;
sendText t) # Send text - show help and exit if too many arguments
exit;; [[ $# -gt 2 ]] && help && exit
h | ?) # display help and exit sendText
help exit;;
exit;; h | ?) # display help and exit
esac help
exit;;
esac
done done
# Send file(s) # Send file(s)
# display help and exit if 2 arguments are given or if file does not exist sendFiles "$@"
[[ $# -eq 2 ]] || [[ ! -a $1 ]] && help && exit
sendFiles "$1"

6
pairdrop-cli/pairdrop.sh Normal file
View file

@ -0,0 +1,6 @@
#!/bin/bash
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P )
cd "$parent_path" || exit
./pairdrop "$@"

Binary file not shown.

View file

@ -0,0 +1,3 @@
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
& "$scriptDir\pairdrop.sh" $args

View file

@ -0,0 +1,20 @@
#!/bin/bash
# edit this to point to the pairdrop-cli executable
pathToPairDropCli="/usr/local/bin/pairdrop-cli/pairdrop"
# Initialize an array
lines=()
# Read each line into the array
while IFS= read -r line; do
lines+=("$line")
done <<< "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"
# Get the length of the array
length=${#lines[@]}
# Remove the last entry
unset 'lines[length-1]'
$pathToPairDropCli "${lines[@]}"

View file

@ -81,201 +81,6 @@
}] }]
} }
}, },
"file_handlers": [
{
"action": "/?file_handler",
"name": "All Files",
"accept": {
"application/cpl+xml": [".cpl"],
"application/gpx+xml": [".gpx"],
"application/gzip": [".gz"],
"application/java-archive": [".jar", ".war", ".ear"],
"application/java-vm": [".class"],
"application/javascript": [".js", ".mjs"],
"application/json": [".json", ".map"],
"application/manifest+json": [".webmanifest"],
"application/msword": [".doc", ".dot", ".wiz"],
"application/octet-stream": [".bin", ".dms", ".lrf", ".mar", ".so", ".dist", ".distz", ".pkg", ".bpk", ".dump", ".elc", ".deploy", ".exe", ".dll", ".deb", ".dmg", ".iso", ".img", ".msi", ".msp", ".msm", ".buffer"],
"application/oda": [".oda"],
"application/oxps": [".oxps"],
"application/pdf": [".pdf"],
"application/pgp-signature": [".asc", ".sig"],
"application/pics-rules": [".prf"],
"application/pkcs7-mime": [".p7c"],
"application/pkix-cert": [".cer"],
"application/postscript": [".ai", ".eps", ".ps"],
"application/rtf": [".rtf"],
"application/vnd.android.package-archive": [".apk"],
"application/vnd.apple.mpegurl": [".m3u", ".m3u8"],
"application/vnd.apple.pkpass": [".pkpass"],
"application/vnd.google-earth.kml+xml": [".kml"],
"application/vnd.google-earth.kmz": [".kmz"],
"application/vnd.ms-cab-compressed": [".cab"],
"application/vnd.ms-excel": [".xls", ".xlm", ".xla", ".xlc", ".xlt", ".xlw"],
"application/vnd.ms-outlook": [".msg"],
"application/vnd.ms-powerpoint": [".ppt", ".pot", ".ppa", ".pps", ".pwz"],
"application/vnd.ms-project": [".mpp", ".mpt"],
"application/vnd.ms-xpsdocument": [".xps"],
"application/vnd.oasis.opendocument.database": [".odb"],
"application/vnd.oasis.opendocument.spreadsheet": [".ods"],
"application/vnd.oasis.opendocument.text": [".odt"],
"application/vnd.openstreetmap.data+xml": [".osm"],
"application/vnd.openxmlformats-officedocument.presentationml.presentation": [".pptx"],
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [".xlsx"],
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": [".docx"],
"application/vnd.tcpdump.pcap": [".pcap", ".cap", ".dmp"],
"application/vnd.wordperfect": [".wpd"],
"application/wasm": [".wasm"],
"application/x-7z-compressed": [".7z"],
"application/x-apple-diskimage": [".dmg"],
"application/x-bcpio": [".bcpio"],
"application/x-bittorrent": [".torrent"],
"application/x-cbr": [".cbr", ".cba", ".cbt", ".cbz", ".cb7"],
"application/x-cdlink": [".vcd"],
"application/x-chrome-extension": [".crx"],
"application/x-cpio": [".cpio"],
"application/x-csh": [".csh"],
"application/x-debian-package": [".deb", ".udeb"],
"application/x-dvi": [".dvi"],
"application/x-freearc": [".arc"],
"application/x-gtar": [".gtar"],
"application/x-hdf": [".hdf"],
"application/x-hdf5": [".h5"],
"application/x-httpd-php": [".php"],
"application/x-iso9660-image": [".iso"],
"application/x-iwork-keynote-sffkey": [".key"],
"application/x-iwork-numbers-sffnumbers": [".numbers"],
"application/x-iwork-pages-sffpages": [".pages"],
"application/x-latex": [".latex"],
"application/x-makeself": [".run"],
"application/x-mif": [".mif"],
"application/x-ms-shortcut": [".lnk"],
"application/x-msaccess": [".mdb"],
"application/x-msdownload": [".exe", ".dll", ".com", ".bat", ".msi"],
"application/x-mspublisher": [".pub"],
"application/x-netcdf": [".cdf", ".nc"],
"application/x-perl": [".pl", ".pm"],
"application/x-pilot": [".prc", ".pdb"],
"application/x-pkcs12": [".p12", ".pfx"],
"application/x-pn-realaudio": [".ram"],
"application/x-python-code": [".pyc", ".pyo"],
"application/x-rar-compressed": [".rar"],
"application/x-redhat-package-manager": [".rpm"],
"application/x-sh": [".sh"],
"application/x-shar": [".shar"],
"application/x-shockwave-flash": [".swf"],
"application/x-sql": [".sql"],
"application/x-subrip": [".srt"],
"application/x-sv4cpio": [".sv4cpio"],
"application/x-sv4crc": [".sv4crc"],
"application/x-tads": [".gam"],
"application/x-tar": [".tar"],
"application/x-tcl": [".tcl"],
"application/x-tex": [".tex"],
"application/x-troff": [".roff", ".t", ".tr"],
"application/x-troff-man": [".man"],
"application/x-troff-me": [".me"],
"application/x-troff-ms": [".ms"],
"application/x-ustar": [".ustar"],
"application/x-wais-source": [".src"],
"application/x-xpinstall": [".xpi"],
"application/xhtml+xml": [".xhtml", ".xht"],
"application/xml": [".xsl", ".rdf", ".wsdl", ".xpdl"],
"application/zip": [".zip"],
"audio/3gpp": [".3gp", ".3gpp"],
"audio/3gpp2": [".3g2", ".3gpp2"],
"audio/aac": [".aac", ".adts", ".loas", ".ass"],
"audio/basic": [".au", ".snd"],
"audio/midi": [".mid", ".midi", ".kar", ".rmi"],
"audio/mpeg": [".mpga", ".mp2", ".mp2a", ".mp3", ".m2a", ".m3a"],
"audio/ogg": [".oga", ".ogg", ".spx", ".opus"],
"audio/opus": [".opus"],
"audio/x-aiff": [".aif", ".aifc", ".aiff"],
"audio/x-flac": [".flac"],
"audio/x-m4a": [".m4a"],
"audio/x-mpegurl": [".m3u"],
"audio/x-ms-wma": [".wma"],
"audio/x-pn-realaudio": [".ra"],
"audio/x-wav": [".wav"],
"font/otf": [".otf"],
"font/ttf": [".ttf"],
"font/woff": [".woff"],
"font/woff2": [".woff2"],
"image/emf": [".emf"],
"image/gif": [".gif"],
"image/heic": [".heic"],
"image/heif": [".heif"],
"image/ief": [".ief"],
"image/jpeg": [".jpeg", ".jpg"],
"image/jpg": [".jpg"],
"image/pict": [".pict", ".pct", ".pic"],
"image/png": [".png"],
"image/svg+xml": [".svg", ".svgz"],
"image/tiff": [".tif", ".tiff"],
"image/vnd.adobe.photoshop": [".psd"],
"image/vnd.djvu": [".djvu", ".djv"],
"image/vnd.dwg": [".dwg"],
"image/vnd.dxf": [".dxf"],
"image/vnd.microsoft.icon": [".ico"],
"image/vnd.ms-dds": [".dds"],
"image/x-3ds": [".3ds"],
"image/x-cmu-raster": [".ras"],
"image/x-icon": [".ico"],
"image/x-ms-bmp": [".bmp"],
"image/x-portable-anymap": [".pnm"],
"image/x-portable-bitmap": [".pbm"],
"image/x-portable-graymap": [".pgm"],
"image/x-portable-pixmap": [".ppm"],
"image/x-rgb": [".rgb"],
"image/x-tga": [".tga"],
"image/x-xbitmap": [".xbm"],
"image/x-xpixmap": [".xpm"],
"image/x-xwindowdump": [".xwd"],
"message/rfc822": [".eml", ".mht", ".mhtml", ".nws"],
"model/obj": [".obj"],
"model/stl": [".stl"],
"model/vnd.collada+xml": [".dae"],
"text/calendar": [".ics", ".ifb"],
"text/css": [".css"],
"text/csv": [".csv"],
"text/html": [".html", ".htm", ".shtml"],
"text/markdown": [".markdown", ".md"],
"text/plain": [".txt", ".text", ".conf", ".def", ".list", ".log", ".in", ".ini"],
"text/richtext": [".rtx"],
"text/rtf": [".rtf"],
"text/tab-separated-values": [".tsv"],
"text/x-c": [".c", ".cc", ".cxx", ".cpp", ".h", ".hh", ".dic"],
"text/x-java-source": [".java"],
"text/x-lua": [".lua"],
"text/x-python": [".py"],
"text/x-setext": [".etx"],
"text/x-sgml": [".sgm", ".sgml"],
"text/x-vcard": [".vcf"],
"text/xml": [".xml"],
"text/xul": [".xul"],
"text/yaml": [".yaml", ".yml"],
"video/3gpp": [".3gp", ".3gpp"],
"video/mp2t": [".ts"],
"video/mp4": [".mp4", ".mp4v", ".mpg4"],
"video/mpeg": [".mpeg", ".m1v", ".mpa", ".mpe", ".mpg"],
"video/quicktime": [".mov", ".qt"],
"video/webm": [".webm"],
"video/x-flv": [".flv"],
"video/x-m4v": [".m4v"],
"video/x-ms-asf": [".asf", ".asx"],
"video/x-ms-vob": [".vob"],
"video/x-ms-wmv": [".wmv"],
"video/x-msvideo": [".avi"],
"video/x-sgi-movie": [".*"]
},
"icons": [
{
"src": "/images/android-chrome-192x192.png",
"sizes": "192x192"
}
]
}
],
"launch_handler": { "launch_handler": {
"client_mode": "focus-existing" "client_mode": "focus-existing"
} }

View file

@ -2545,6 +2545,7 @@ class WebShareTargetUI {
} }
} }
// Keep for legacy reasons even though this is removed from new PWA installations
class WebFileHandlersUI { class WebFileHandlersUI {
async evaluateLaunchQueue() { async evaluateLaunchQueue() {
if (!"launchQueue" in window) return; if (!"launchQueue" in window) return;