SVNからのミラー
This commit is contained in:
23
CHANGELOG.md
Normal file
23
CHANGELOG.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# 0.3.1 (2024/05/??)
|
||||
* Minix、Haiku、とmacOSでコンパイル出来る様に
|
||||
|
||||
# 0.3.0 (2024/05/31)
|
||||
* CDNの回避
|
||||
* Pixivからダウンロード出来る様に
|
||||
* NetBSDは「/usr/pkg」→「/usr/local」
|
||||
* HTTPステータス200だけの場合をダウンロードする様に
|
||||
* ダウンロードに失敗する場合、ファイルを消す
|
||||
* 1つ以上のファイルがダウンロードに失敗する場合、正しく状況を知らせる様に
|
||||
* 予行演習モード
|
||||
* `make release-freebsd`の修正
|
||||
* 使い方の修正
|
||||
* 「ダウンロード中」や「ダウンロード済み」状況を表示する事が不要
|
||||
|
||||
# 0.2.0 (2024/04/26)
|
||||
* ファイル名はパラメートルを付いたら、ファイル名は拡張子に
|
||||
* 名前として保存オプション
|
||||
* manpageの追加
|
||||
* ファイルが既に存在したら、ダウンロードに終了するオプション
|
||||
|
||||
# 0.1.0 (2024/04/22)
|
||||
* 最初リリース
|
||||
13
LICENSE.txt
Normal file
13
LICENSE.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright © 2018-2024 by 076.moe
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
106
Makefile
Normal file
106
Makefile
Normal file
@@ -0,0 +1,106 @@
|
||||
UNAME_S != uname -s
|
||||
UNAME_M != uname -m
|
||||
OS = ${UNAME_S}
|
||||
|
||||
.if ${UNAME_S} == "OpenBSD"
|
||||
OS = openbsd
|
||||
.elif ${UNAME_S} == "NetBSD"
|
||||
OS = netbsd
|
||||
.elif ${UNAME_S} == "FreeBSD"
|
||||
OS = freebsd
|
||||
.elif ${UNAME_S} == "Linux"
|
||||
OS = linux
|
||||
.endif
|
||||
|
||||
NAME != cat main.c | grep "const char\* sofname" | awk '{print $$5}' | \
|
||||
sed "s/\"//g" | sed "s/;//"
|
||||
VERSION != cat main.c | grep "const char\* version" | awk '{print $$5}' | \
|
||||
sed "s/\"//g" | sed "s/;//"
|
||||
PREFIX = /usr/local
|
||||
.if ${UNAME_S} == "Linux"
|
||||
PREFIX = /usr
|
||||
.elif ${UNAME_S} == "Haiku"
|
||||
PREFIX = /boot/home/config/non-packaged
|
||||
.elif ${UNAME_S} == "Darwin"
|
||||
.endif
|
||||
|
||||
MANPREFIX = ${PREFIX}/share/man
|
||||
.if ${UNAME_S} == "OpenBSD"
|
||||
MANPREFIX = ${PREFIX}/man
|
||||
.elif ${UNAME_S} == "Haiku"
|
||||
MANPREFIX = ${PREFIX}/documentation/man
|
||||
.endif
|
||||
|
||||
CFLAGS = -Wall -Wextra -g -I/usr/include -I/usr/local/include
|
||||
LDFLAGS = -L/usr/lib -L/usr/local/lib
|
||||
|
||||
.if ${UNAME_S} == "NetBSD" || ${UNAME_S} == "Minix"
|
||||
CFLAGS += -I/usr/pkg/include
|
||||
LDFLAGS += -L/usr/pkg/lib
|
||||
.elif ${UNAME_S} == "Haiku"
|
||||
CFLAGS += -I/boot/system/develop/headers
|
||||
LDFLAGS += -L/boot/system/develop/lib
|
||||
.elif ${UNAME_S} == "Darwin"
|
||||
CFLAGS += -I/opt/local/include
|
||||
LDFLAGS += -L/opt/local/lib
|
||||
.endif
|
||||
|
||||
CC = cc
|
||||
.if ${UNAME_S} == "Minix"
|
||||
CC = clang
|
||||
.endif
|
||||
|
||||
FILES = main.c
|
||||
LIBS = -lcurl
|
||||
|
||||
STATIC = -static ${LIBS}
|
||||
.if ${UNAME_S} == "OpenBSD"
|
||||
STATIC += -lc -lnghttp3 -lngtcp2_crypto_quictls -lngtcp2 -lssl -lcrypto -lnghttp2\
|
||||
-lz -lpthread
|
||||
.elif ${UNAME_S} == "FreeBSD"
|
||||
STATIC += -liconv -lc -lnghttp2 -lssh2 -lpsl -lssl -lheimntlm -lhx509 -lcom_err\
|
||||
-lcrypto -lasn1 -lwind -lheimbase -lroken -lcrypt -lz -lkrb5 -lgssapi\
|
||||
-lgssapi_krb5 -lthr -lidn2 -lunistring -lprivateheimipcc
|
||||
.elif ${UNAME_S} == "NetBSD"
|
||||
STATIC += -lnghttp2 -lc -lidn2 -lunistring -lgssapi -lkrb5 -lhx509 -lintl -lssl\
|
||||
-lcrypto -lcrypt -lasn1 -lcom_err -lroken -lutil -lwind -lheimbase\
|
||||
-lheimntlm -lz -lpthread
|
||||
.elif ${UNAME_S} == "Linux"
|
||||
STATIC += -lc -lnghttp2 -lidn2 -lssh2 -lpsl -lssl -lcrypto -lzstd -lz -lunistring
|
||||
.endif
|
||||
|
||||
all:
|
||||
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS} ${LIBS}
|
||||
strip ${NAME}
|
||||
|
||||
clean:
|
||||
rm -f ${NAME}
|
||||
|
||||
dist:
|
||||
mkdir -p ${NAME}-${VERSION} release/src
|
||||
cp -R LICENSE.txt Makefile README.md CHANGELOG.md\
|
||||
${NAME}.1 ${FILES} ${NAME}-${VERSION}
|
||||
tar zcfv release/src/${NAME}-${VERSION}.tar.gz ${NAME}-${VERSION}
|
||||
rm -rf ${NAME}-${VERSION}
|
||||
|
||||
man:
|
||||
mkdir -p release/man/${VERSION}
|
||||
sed "s/VERSION/${VERSION}/g" < ${NAME}.1 > release/man/${VERSION}/${NAME}.1
|
||||
|
||||
release:
|
||||
mkdir -p release/bin/${VERSION}/${OS}/${UNAME_M}
|
||||
${CC} ${CFLAGS} -o release/bin/${VERSION}/${OS}/${UNAME_M}/${NAME}\
|
||||
${FILES} ${LDFLAGS} ${STATIC}
|
||||
strip release/bin/${VERSION}/${OS}/${UNAME_M}/${NAME}
|
||||
|
||||
install:
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin ${DESTDOR}${MANPREFIX}/man1
|
||||
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
|
||||
sed "s/VERSION/${VERSION}/g" < ${NAME}.1 > ${DESTDIR}${MANPREFIX}/man1/${NAME}.1
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||
|
||||
uninstall:
|
||||
rm -f ${DESTDIR}${MANPREFIX}/man1/${NAME}.1
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||
|
||||
.PHONY: all clean dist man release install uninstall
|
||||
62
README.md
Normal file
62
README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# odl - オンライン・ダウンロード
|
||||
|
||||
## インストールする方法
|
||||
### OpenBSD
|
||||
```sh
|
||||
doas pkg_add curl
|
||||
make
|
||||
doas make install
|
||||
```
|
||||
|
||||
### Void Linux
|
||||
```sh
|
||||
doas xbps-install curl bmake
|
||||
bmake
|
||||
doas bmake install
|
||||
```
|
||||
|
||||
### FreeBSD
|
||||
```sh
|
||||
doas pkg install curl
|
||||
make
|
||||
doas make install
|
||||
```
|
||||
|
||||
### NetBSD
|
||||
```sh
|
||||
doas pkgin install curl
|
||||
make
|
||||
doas make install
|
||||
```
|
||||
|
||||
### CRUX Linux
|
||||
```sh
|
||||
doas prt-get depinst curl bmake
|
||||
bmake
|
||||
doas bmake install
|
||||
```
|
||||
|
||||
### Minix
|
||||
```sh
|
||||
su
|
||||
pkgin install curl clang bmake
|
||||
bmake
|
||||
bmake install
|
||||
```
|
||||
|
||||
### Haiku
|
||||
```sh
|
||||
pkgman install curl curl_devel bmake
|
||||
bmake
|
||||
bmake install
|
||||
```
|
||||
|
||||
### macOS
|
||||
```sh
|
||||
brew install curl bmake
|
||||
bmake
|
||||
doas bmake install
|
||||
```
|
||||
|
||||

|
||||

|
||||
274
main.c
Normal file
274
main.c
Normal file
@@ -0,0 +1,274 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
const char* sofname = "odl";
|
||||
const char* version = "0.3.1";
|
||||
const char* avalopt = "nopv";
|
||||
char* filename;
|
||||
|
||||
int opt;
|
||||
int optind;
|
||||
int yokou_flag = 0;
|
||||
int output_flag = 0;
|
||||
int version_flag = 0;
|
||||
int already_flag = 0;
|
||||
int err_flag = 0;
|
||||
int dlstat = 0;
|
||||
int onedlsuc = 0;
|
||||
|
||||
char* get_filename(const char* url) {
|
||||
char* fn_start = strrchr(url, '/');
|
||||
if (fn_start == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
fn_start++;
|
||||
|
||||
char* query = strchr(fn_start, '?');
|
||||
char* anchor = strchr(fn_start, '#');
|
||||
char* fn_end = NULL;
|
||||
|
||||
if (query != NULL && anchor != NULL) {
|
||||
fn_end = (query < anchor) ? query : anchor;
|
||||
} else if (query != NULL) {
|
||||
fn_end = query;
|
||||
} else if (anchor != NULL) {
|
||||
fn_end = anchor;
|
||||
}
|
||||
|
||||
// URLでパラメートルがなければ、そのままファイル名をコピーして
|
||||
if (fn_end == NULL) {
|
||||
fn_end = strchr(fn_start, '\0');
|
||||
}
|
||||
|
||||
size_t length = fn_end - fn_start;
|
||||
|
||||
char* extfn = malloc(length + 1);
|
||||
if (extfn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(extfn, fn_start, length);
|
||||
extfn[length] = '\0';
|
||||
|
||||
return extfn;
|
||||
}
|
||||
|
||||
int progress_callback(void *cp, double dt, double dn, double ut, double un) {
|
||||
(void)cp;
|
||||
(void)ut;
|
||||
(void)un;
|
||||
|
||||
double progress = (dn / dt) * 100.0;
|
||||
|
||||
printf("\r[");
|
||||
int barw = 50;
|
||||
int pos = (int)(progress * barw / 100.0);
|
||||
|
||||
for (int i = 0; i < barw; ++i) {
|
||||
if (i < pos) printf("=");
|
||||
else if (i == pos) printf(">");
|
||||
else printf(" ");
|
||||
}
|
||||
|
||||
printf("] %.2f%% %s", progress, filename);
|
||||
fflush(stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handle_o(int argc, char* argv[]) {
|
||||
output_flag = 1;
|
||||
if (optind < argc) {
|
||||
if (filename != NULL) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"-oをご利用する場合、1つのファイルだけをダウンロード出来ます。\n"
|
||||
);
|
||||
}
|
||||
filename = argv[optind];
|
||||
} else {
|
||||
fprintf(stderr, "-oの後でファイル名がありません。");
|
||||
err_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void dlsucmsg() {
|
||||
if (yokou_flag == 0) printf("\nダウンロードに完了しました。\n");
|
||||
else {
|
||||
printf("\nダウンロードに完了しました。\n");
|
||||
printf("予行演習モードですので、ファイルを保存していません。\n");
|
||||
printf("保存するには、「-n」フラグを消して下さい。\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usage() {
|
||||
printf("%s-%s\nusage: %s [-%s] [url ...]\n", sofname, version, sofname, avalopt);
|
||||
}
|
||||
|
||||
void flags(int opt, int argc, char* argv[]) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
yokou_flag = 1;
|
||||
break;
|
||||
case 'o':
|
||||
handle_o(argc, argv);
|
||||
break;
|
||||
case 'p':
|
||||
already_flag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
version_flag = 1;
|
||||
break;
|
||||
default:
|
||||
err_flag = 1;
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int downloader(CURL* curl, char* filename, const char* url) {
|
||||
if (already_flag == 1 && access(filename, F_OK) != -1) {
|
||||
printf("ファイルが既に存在しますので、ダウンロードしません。\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
|
||||
// Clownflareは面倒くさいわね・・・
|
||||
curl_easy_setopt(
|
||||
curl,
|
||||
CURLOPT_USERAGENT,
|
||||
"Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0"
|
||||
);
|
||||
// Pixivも結構面倒くさい
|
||||
if (
|
||||
strstr("s.pixiv.net", url) == 0 ||
|
||||
strstr("i.pixiv.net", url) == 0 ||
|
||||
strstr("s.pximg.net", url) == 0 ||
|
||||
strstr("i.pximg.net", url) == 0
|
||||
) {
|
||||
curl_easy_setopt(curl, CURLOPT_REFERER, "https://www.pixiv.net/");
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
|
||||
FILE* file = NULL;
|
||||
|
||||
if (yokou_flag == 0) {
|
||||
file = fopen(filename, "wb");
|
||||
} else {
|
||||
file = fopen("/tmp/odl_test", "wb");
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
perror("ファイルを開けません。");
|
||||
curl_easy_cleanup(curl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
|
||||
|
||||
long httpcode = 0;
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpcode);
|
||||
|
||||
fclose(file);
|
||||
if (yokou_flag == 1) unlink("/tmp/odl_test");
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
if (yokou_flag == 0) unlink(filename);
|
||||
fprintf(stderr, "\nダウンロードに失敗: %s\n", curl_easy_strerror(res));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res == CURLE_ABORTED_BY_CALLBACK || httpcode != 200) {
|
||||
if (yokou_flag == 0) unlink(filename);
|
||||
fprintf(stderr, "\n%sをダウンロードに失敗: HTTP CODE: %ld\n", filename, httpcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, avalopt)) != -1) {
|
||||
flags(opt, argc, argv);
|
||||
}
|
||||
|
||||
if (err_flag == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (version_flag == 1) {
|
||||
printf("%s-%s\n", sofname, version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
perror("curlを初期設置に失敗。");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 一つのファイルだけが可能
|
||||
if (output_flag == 1) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "-oの後でURLがありません。");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (filename == NULL) {
|
||||
fprintf(stderr, "-oの後でファイル名がありません。");
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = argv[optind];
|
||||
const char* url = argv[optind+1];
|
||||
dlstat = downloader(curl, filename, url);
|
||||
if (dlstat == 0) onedlsuc = 1;
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (onedlsuc == 1) {
|
||||
dlsucmsg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 複数ファイル名可能
|
||||
for (int i = optind; i < argc; i++) {
|
||||
const char* url = argv[i];
|
||||
filename = get_filename(url);
|
||||
if (filename == NULL) {
|
||||
fprintf(stderr, "URLからファイル名を抽出出来ませんでした。\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
dlstat = downloader(curl, filename, url);
|
||||
free(filename);
|
||||
if (dlstat == 0) onedlsuc = 1;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
if (onedlsuc == 1) {
|
||||
dlsucmsg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
25
odl.1
Normal file
25
odl.1
Normal file
@@ -0,0 +1,25 @@
|
||||
.TH ODL 1 VERSION
|
||||
.SH NAME
|
||||
odl - onrain downloader
|
||||
.SH SYNOPSIS
|
||||
.B odl
|
||||
[-v] [-o \fI\,name\fR \fI\,file\fR] [-pn] \fI\,file\fR [\fI\,...\fR]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
ネットから簡単にファイルをダウンロード出来るツールです。
|
||||
.TP
|
||||
-\fB\,n\fR \fI\,file\fR \fI\,...\fR
|
||||
ファイル保存せずにダウンロードが可能かどうか確認出来る。
|
||||
.TP
|
||||
-\fB\,o\fR \fI\,name\fR \fI\,file\fR
|
||||
ファイル名を付いてダウンロードします。
|
||||
それで1回1つのファイルのみダウンロード可能です。
|
||||
.TP
|
||||
-\fB\,p\fR \fI\,file\fR \fI\,...\fR
|
||||
ファイルは既に存在する場合、ダウンロードしない様にします。
|
||||
.TP
|
||||
-\fB\,v\fR
|
||||
バージョンを表示
|
||||
.SH AUTHORS
|
||||
.PP
|
||||
テクニカル諏訪子
|
||||
BIN
scrot1.png
Executable file
BIN
scrot1.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 250 KiB |
BIN
scrot2.png
Executable file
BIN
scrot2.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 505 KiB |
Reference in New Issue
Block a user