SVNからのミラー

This commit is contained in:
2026-01-06 21:17:47 +09:00
commit 17eda7062b
8 changed files with 503 additions and 0 deletions

23
CHANGELOG.md Normal file
View 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
View 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
View 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
View 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
```
![](scrot1.png)
![](scrot2.png)

274
main.c Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

BIN
scrot2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 KiB