Compare commits

..

8 Commits

7
.gitignore vendored

@ -4,14 +4,7 @@ venv/*
.idea/ .idea/
__pycache__/ __pycache__/
__pycache__/* __pycache__/*
__pycache__/config.cpython-37.pyc
app/__pycache__/ app/__pycache__/
app/__pycache__/* app/__pycache__/*
app/__pycache__/__init__.cpython-37.pyc
app/__pycache__/views.cpython-37.pyc
app/static/dewatermark/ app/static/dewatermark/
app/static/dewatermark/* app/static/dewatermark/*
app/static/republish/
app/static/republish/*
app/static/covers/*
*.pyc

@ -1,21 +1,18 @@
# Run # Run
## in Development ## in Development
**only using flask; no Unicorn**
`export FLASK_APP=run.py` `export FLASK_APP=run.py`
`export FLASK_ENV=development` `export FLASK_ENV=development`
`flask run` `flask run`
**Using gunicorn:** **Using gunicorn:**
`gunicorn --env SCRIPT_NAME=/watermark -w 4 -b 127.0.0.1:5000 app:app --log-level debug` `gunicorn --env SCRIPT_NAME=/watermarks -w 4 -b 127.0.0.1:5000 app:app --log-level debug`
* `-w` workers * `-w` workers
* `-b` bind to address / unix socker * `-b` bind to address / unix socker
**And gunicorn with using unix sock:** (this how it should run in production) **And gunicorn with using unix sock:** (this how it should run in production)
` gunicorn --env SCRIPT_NAME=/watermark --workers 4 --bind unix:app.sock -m 007 app:app --log-level debug ` gunicorn --env SCRIPT_NAME=/watermarks --workers 4 --bind unix:app.sock -m 007 app:app --log-level debug
## in Production with gunicorn and unix sockets ## in Production with gunicorn and unix sockets
Based on https://medium.com/faun/deploy-flask-app-with-nginx-using-gunicorn-7fda4f50066a Based on https://medium.com/faun/deploy-flask-app-with-nginx-using-gunicorn-7fda4f50066a
@ -78,18 +75,14 @@ But in the long run logging should be disabled
---- ----
09.06.2020 Handling url path /watermarks 09.06.2020 Handling url path /watermarks
* gunicorn has to be started with argument `--env SCRIPT_NAME=/watermark` which defines its path: * gunicorn has to be started with argument `--env SCRIPT_NAME=/watermarks` which defines its path:
`gunicorn --env SCRIPT_NAME=/watermark --workers 4 --bind unix:app.sock -m 007 app:app --log-level debug` `gunicorn --env SCRIPT_NAME=/watermarks --workers 4 --bind unix:app.sock -m 007 app:app --log-level debug`
* allows for the following URLs * allows for the following URLs
* http://127.0.0.1/watermark * http://127.0.0.1/watermarks
* http://127.0.0.1/watermark/uploadbook * http://127.0.0.1/watermarks/uploadbook
* http://127.0.0.1/watermark/about * http://127.0.0.1/watermarks/about
* added page /test `watermark/test` for testing url_for() - correct * added page /test `watermarks/test` for testing url_for() - correct
* made urls relative * made urls relative
* service file with `--env SCRIPT_NAME=/watermark` see above * service file with `--env SCRIPT_NAME=/watermarks` see above
* *
gunicorn -w 4 -b :5000 app:app
gunicorn -w 4 -b :5000 app:app
#

Binary file not shown.

@ -97,370 +97,3 @@
[2020-05-24 01:33:11 +0100] [24583] [INFO] Worker exiting (pid: 24583) [2020-05-24 01:33:11 +0100] [24583] [INFO] Worker exiting (pid: 24583)
[2020-05-24 01:33:11 +0100] [24581] [INFO] Worker exiting (pid: 24581) [2020-05-24 01:33:11 +0100] [24581] [INFO] Worker exiting (pid: 24581)
[2020-05-24 01:33:11 +0100] [24579] [INFO] Shutting down: Master [2020-05-24 01:33:11 +0100] [24579] [INFO] Shutting down: Master
[2020-06-19 12:26:51 +0100] [28382] [DEBUG] Current configuration:
config: None
bind: ['unix:app.sock']
backlog: 2048
workers: 4
worker_class: sync
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /var/www/TacticalApp
daemon: False
raw_env: []
pidfile: None
worker_tmp_dir: None
user: 0
group: 0
umask: 7
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: None
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: /var/www/TacticalApp/app.log
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
dogstatsd_tags:
statsd_prefix:
proc_name: None
default_proc_name: app:app
pythonpath: None
paste: None
on_starting: <function OnStarting.on_starting at 0xb5e263d8>
on_reload: <function OnReload.on_reload at 0xb5e26468>
when_ready: <function WhenReady.when_ready at 0xb5e264f8>
pre_fork: <function Prefork.pre_fork at 0xb5e265d0>
post_fork: <function Postfork.post_fork at 0xb5e26660>
post_worker_init: <function PostWorkerInit.post_worker_init at 0xb5e26738>
worker_int: <function WorkerInt.worker_int at 0xb5e267c8>
worker_abort: <function WorkerAbort.worker_abort at 0xb5e26858>
pre_exec: <function PreExec.pre_exec at 0xb5e268e8>
pre_request: <function PreRequest.pre_request at 0xb5e26978>
post_request: <function PostRequest.post_request at 0xb5e269c0>
child_exit: <function ChildExit.child_exit at 0xb5e26a98>
worker_exit: <function WorkerExit.worker_exit at 0xb5e26b28>
nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0xb5e26bb8>
on_exit: <function OnExit.on_exit at 0xb5e26c48>
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: None
raw_paste_global_conf: []
strip_header_spaces: False
[2020-06-19 12:26:51 +0100] [28382] [INFO] Starting gunicorn 20.0.4
[2020-06-19 12:26:51 +0100] [28382] [DEBUG] Arbiter booted
[2020-06-19 12:26:51 +0100] [28382] [INFO] Listening at: unix:app.sock (28382)
[2020-06-19 12:26:51 +0100] [28382] [INFO] Using worker: sync
[2020-06-19 12:26:51 +0100] [28385] [INFO] Booting worker with pid: 28385
[2020-06-19 12:26:51 +0100] [28386] [INFO] Booting worker with pid: 28386
[2020-06-19 12:26:51 +0100] [28387] [INFO] Booting worker with pid: 28387
[2020-06-19 12:26:51 +0100] [28388] [INFO] Booting worker with pid: 28388
[2020-06-19 12:26:51 +0100] [28382] [DEBUG] 4 workers
[2020-06-19 12:26:54 +0100] [28387] [DEBUG] worker: SIGWINCH ignored.
[2020-06-19 12:26:54 +0100] [28385] [DEBUG] worker: SIGWINCH ignored.
[2020-06-19 12:26:54 +0100] [28386] [DEBUG] worker: SIGWINCH ignored.
[2020-06-19 12:26:54 +0100] [28382] [INFO] Handling signal: winch
[2020-06-19 12:26:54 +0100] [28382] [DEBUG] SIGWINCH ignored. Not daemonized
[2020-06-19 12:26:54 +0100] [28388] [DEBUG] worker: SIGWINCH ignored.
[2020-06-19 12:27:26 +0100] [28386] [DEBUG] GET /index.html
[2020-06-19 12:27:34 +0100] [28386] [DEBUG] GET /
[2020-06-19 12:28:03 +0100] [28382] [INFO] Handling signal: int
[2020-06-19 12:28:03 +0100] [28386] [INFO] Worker exiting (pid: 28386)
[2020-06-19 12:28:03 +0100] [28387] [INFO] Worker exiting (pid: 28387)
[2020-06-19 12:28:03 +0100] [28385] [INFO] Worker exiting (pid: 28385)
[2020-06-19 12:28:03 +0100] [28388] [INFO] Worker exiting (pid: 28388)
[2020-06-19 12:28:03 +0100] [28382] [INFO] Shutting down: Master
[2020-06-19 12:29:23 +0100] [28474] [DEBUG] Current configuration:
config: None
bind: ['unix:app.sock']
backlog: 2048
workers: 4
worker_class: sync
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /var/www/TacticalApp
daemon: False
raw_env: ['SCRIPT_NAME=/watermark']
pidfile: None
worker_tmp_dir: None
user: 0
group: 0
umask: 7
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: None
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: /var/www/TacticalApp/app.log
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
dogstatsd_tags:
statsd_prefix:
proc_name: None
default_proc_name: -
pythonpath: None
paste: None
on_starting: <function OnStarting.on_starting at 0xb5dc73d8>
on_reload: <function OnReload.on_reload at 0xb5dc7468>
when_ready: <function WhenReady.when_ready at 0xb5dc74f8>
pre_fork: <function Prefork.pre_fork at 0xb5dc75d0>
post_fork: <function Postfork.post_fork at 0xb5dc7660>
post_worker_init: <function PostWorkerInit.post_worker_init at 0xb5dc7738>
worker_int: <function WorkerInt.worker_int at 0xb5dc77c8>
worker_abort: <function WorkerAbort.worker_abort at 0xb5dc7858>
pre_exec: <function PreExec.pre_exec at 0xb5dc78e8>
pre_request: <function PreRequest.pre_request at 0xb5dc7978>
post_request: <function PostRequest.post_request at 0xb5dc79c0>
child_exit: <function ChildExit.child_exit at 0xb5dc7a98>
worker_exit: <function WorkerExit.worker_exit at 0xb5dc7b28>
nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0xb5dc7bb8>
on_exit: <function OnExit.on_exit at 0xb5dc7c48>
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: None
raw_paste_global_conf: []
strip_header_spaces: False
[2020-06-19 12:29:23 +0100] [28474] [INFO] Starting gunicorn 20.0.4
[2020-06-19 12:29:23 +0100] [28474] [DEBUG] Arbiter booted
[2020-06-19 12:29:23 +0100] [28474] [INFO] Listening at: unix:app.sock (28474)
[2020-06-19 12:29:23 +0100] [28474] [INFO] Using worker: sync
[2020-06-19 12:29:23 +0100] [28477] [INFO] Booting worker with pid: 28477
[2020-06-19 12:29:23 +0100] [28477] [ERROR] Exception in worker process
Traceback (most recent call last):
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/workers/base.py", line 119, in init_process
self.load_wsgi()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi
self.wsgi = self.app.wsgi()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 49, in load
return self.load_wsgiapp()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp
return util.import_app(self.app_uri)
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/util.py", line 358, in import_app
mod = importlib.import_module(module)
File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
ModuleNotFoundError: No module named '-'
[2020-06-19 12:29:23 +0100] [28477] [INFO] Worker exiting (pid: 28477)
[2020-06-19 12:29:23 +0100] [28478] [INFO] Booting worker with pid: 28478
[2020-06-19 12:29:23 +0100] [28479] [INFO] Booting worker with pid: 28479
[2020-06-19 12:29:23 +0100] [28478] [ERROR] Exception in worker process
Traceback (most recent call last):
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/workers/base.py", line 119, in init_process
self.load_wsgi()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi
self.wsgi = self.app.wsgi()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 49, in load
return self.load_wsgiapp()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp
return util.import_app(self.app_uri)
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/util.py", line 358, in import_app
mod = importlib.import_module(module)
File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
ModuleNotFoundError: No module named '-'
[2020-06-19 12:29:23 +0100] [28478] [INFO] Worker exiting (pid: 28478)
[2020-06-19 12:29:23 +0100] [28479] [ERROR] Exception in worker process
Traceback (most recent call last):
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/workers/base.py", line 119, in init_process
self.load_wsgi()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi
self.wsgi = self.app.wsgi()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 49, in load
return self.load_wsgiapp()
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp
return util.import_app(self.app_uri)
File "/var/www/TacticalApp/venv/lib/python3.7/site-packages/gunicorn/util.py", line 358, in import_app
mod = importlib.import_module(module)
File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
ModuleNotFoundError: No module named '-'
[2020-06-19 12:29:23 +0100] [28479] [INFO] Worker exiting (pid: 28479)
[2020-06-19 12:29:23 +0100] [28474] [INFO] Shutting down: Master
[2020-06-19 12:29:23 +0100] [28474] [INFO] Reason: Worker failed to boot.
[2020-06-19 12:29:37 +0100] [28480] [DEBUG] Current configuration:
config: None
bind: ['unix:app.sock']
backlog: 2048
workers: 4
worker_class: sync
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /var/www/TacticalApp
daemon: False
raw_env: []
pidfile: None
worker_tmp_dir: None
user: 0
group: 0
umask: 7
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: None
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: /var/www/TacticalApp/app.log
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
dogstatsd_tags:
statsd_prefix:
proc_name: None
default_proc_name: app:app
pythonpath: None
paste: None
on_starting: <function OnStarting.on_starting at 0xb5dae3d8>
on_reload: <function OnReload.on_reload at 0xb5dae468>
when_ready: <function WhenReady.when_ready at 0xb5dae4f8>
pre_fork: <function Prefork.pre_fork at 0xb5dae5d0>
post_fork: <function Postfork.post_fork at 0xb5dae660>
post_worker_init: <function PostWorkerInit.post_worker_init at 0xb5dae738>
worker_int: <function WorkerInt.worker_int at 0xb5dae7c8>
worker_abort: <function WorkerAbort.worker_abort at 0xb5dae858>
pre_exec: <function PreExec.pre_exec at 0xb5dae8e8>
pre_request: <function PreRequest.pre_request at 0xb5dae978>
post_request: <function PostRequest.post_request at 0xb5dae9c0>
child_exit: <function ChildExit.child_exit at 0xb5daea98>
worker_exit: <function WorkerExit.worker_exit at 0xb5daeb28>
nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0xb5daebb8>
on_exit: <function OnExit.on_exit at 0xb5daec48>
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: None
raw_paste_global_conf: []
strip_header_spaces: False
[2020-06-19 12:29:37 +0100] [28480] [INFO] Starting gunicorn 20.0.4
[2020-06-19 12:29:37 +0100] [28480] [DEBUG] Arbiter booted
[2020-06-19 12:29:37 +0100] [28480] [INFO] Listening at: unix:app.sock (28480)
[2020-06-19 12:29:37 +0100] [28480] [INFO] Using worker: sync
[2020-06-19 12:29:37 +0100] [28483] [INFO] Booting worker with pid: 28483
[2020-06-19 12:29:37 +0100] [28484] [INFO] Booting worker with pid: 28484
[2020-06-19 12:29:38 +0100] [28485] [INFO] Booting worker with pid: 28485
[2020-06-19 12:29:38 +0100] [28486] [INFO] Booting worker with pid: 28486
[2020-06-19 12:29:38 +0100] [28480] [DEBUG] 4 workers
[2020-06-19 12:29:39 +0100] [28480] [INFO] Handling signal: int
[2020-06-19 12:29:39 +0100] [28483] [INFO] Worker exiting (pid: 28483)
[2020-06-19 12:29:39 +0100] [28484] [INFO] Worker exiting (pid: 28484)
[2020-06-19 12:29:39 +0100] [28485] [INFO] Worker exiting (pid: 28485)
[2020-06-19 12:29:40 +0100] [28480] [INFO] Shutting down: Master

@ -3,10 +3,9 @@ from flask import Flask
app = Flask(__name__) app = Flask(__name__)
if app.config["ENV"] == "production": if app.config["ENV"] == "production":
app.config['SERVER_NAME'] = '10.0.0.105' app.config.from_object("config.ProductionConfig")
else: else:
app.config.from_object("config.DevelopmentConfig") app.config.from_object("config.DevelopmentConfig")
app.config['SERVER_NAME'] = '127.0.0.1:5000'
from app import views from app import views

@ -20,8 +20,7 @@
font-family: "Favorit"; font-family: "Favorit";
src: url("Favorit_Medium.ttf"); src: url("Favorit_Medium.ttf");
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;}
}
@font-face { @font-face {
font-family: "Favorit"; font-family: "Favorit";
@ -48,25 +47,21 @@ h3{
transform: scaleX(0.75); transform: scaleX(0.75);
transform-origin: 0 0; transform-origin: 0 0;
font-size: calc(10px + 0.3vw); font-size: calc(10px + 0.3vw);
font-family: "Favorit", Arial, Helvetica, sans-serif;
} }
h4{ h4{
font-weight: 400; font-weight: 400;
margin-bottom: 5px; margin-bottom: 20px;
text-transform: uppercase; text-transform: uppercase;
transform: scaleX(0.75); transform: scaleX(0.75);
transform-origin: 0 0; transform-origin: 0 0;
font-size: calc(10px + 0.3vw); font-size: calc(10px + 0.3vw);
font-family: "Favorit", Arial, Helvetica, sans-serif;
} }
a{ a{
color: #000; color: #000;
text-decoration: none; text-decoration: none;
display: inline; display: inline;
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-weight: 300;
} }
a:hover{ a:hover{
@ -116,6 +111,69 @@ a.mapping:hover{
cursor: pointer; cursor: pointer;
} }
/* INDEX */
h1{
color: #FFF;
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(15px + 5vw);
text-align: center;
width: 100vw;
padding-bottom: 15px;
}
#indexabout{
padding-top: 20vh;
padding-bottom: 25px;
}
dl{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-size: calc(12px + 0.3vw);
text-align: center;
width: 100vw;
font-weight: 400;
font-style: italic;
transform: scaleX(0.75);
line-height: 110%;
}
.colorbackground{
margin-top: -5px;
position: absolute;
overflow: hidden;
width: 100vw;
height: 100vh;
z-index: 1;
}
#indexyellowleft{
position: fixed;
left: 0;
top: 0;
display: inline-block;
width: 38vw;
height: 100vh;
background-color: #cfff00;
}
#indexyellowright{
position: fixed;
left: 76vw;
top: 0;
display: inline-block;
height: 100vh;
width: 24vw;
background-color: #cfff00;
}
.indextext{
position: fixed;
z-index: 2;
}
/* HEADER */ /* HEADER */
header{ header{
@ -153,7 +211,6 @@ a.head{
color: #FFF; color: #FFF;
text-decoration: none; text-decoration: none;
display: inline; display: inline;
font-family: "Lyon", Arial, Helvetica, sans-serif;
} }
a.head:hover{ a.head:hover{
@ -187,8 +244,7 @@ a.head:visited{
.scrollrequests{ .scrollrequests{
overflow: auto; overflow: auto;
height: 85%; height: 100%;
margin-bottom: 100px;
} }
.booksrequested{ .booksrequested{
@ -300,154 +356,3 @@ figcaption{
transform-origin: 0 0; transform-origin: 0 0;
font-size: calc(7px + 0.3vw); font-size: calc(7px + 0.3vw);
} }
/* TEXT ABOUT */
.indentedblock{
padding-left: 15px;
padding-bottom: 30px;
}
h5{
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(15px + 0.3vw);
}
.aboutparagraph{
font-family: "Favorit", Arial, Helvetica, sans-serif;
width: 600px;
padding-bottom: 15px;
font-size: calc(10px + 0.3vw);
font-weight: 300;
font-style: normal;
}
.aboutlastparagraph{
width: 600px;
padding-bottom: 50px;
font-size: calc(10px + 0.3vw);
font-weight: 300;
font-style: normal;
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
/* GUIDELINES */
.subfour{
transform: scaleX(0.65);
padding-bottom: 20px;
}
blockquote{
width: 600px;
padding-bottom: 30px;
font-size: calc(10px + 0.3vw);
font-style: italic;
padding-top: 5px;
transform: scaleX(0.85);
transform-origin: 0 0;
font-weight: 300;
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
dd{
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
.termslastparagraph{
width: 600px;
padding-bottom: 25px;
font-size: calc(10px + 0.3vw);
}
dd{
line-height: 115%;
padding-bottom: 5px;
width: 600px;
font-size: calc(10px + 0.3vw);
font-weight: 300;
}
.bulletnumber{
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(10px + 0.3vw);
}
p{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-weight: 300;
}
label{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-weight: 300;
}
.explainspace{
font-size: calc(8px + 0.25vw);
line-height: 110%;
}
/* INDEX */
h1{
color: #FFF;
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(15px + 5vw);
text-align: center;
width: 100vw;
padding-bottom: 15px;
}
#indexabout{
padding-top: 20vh;
padding-bottom: 25px;
}
dl{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-size: calc(12px + 0.3vw);
text-align: center;
width: 100vw;
font-weight: 400;
font-style: italic;
transform: scaleX(0.75);
line-height: 110%;
}
.colorbackground{
margin-top: -5px;
position: absolute;
overflow: hidden;
width: 100vw;
height: 100vh;
z-index: 1;
}
#indexyellowleft{
position: fixed;
left: 0;
top: 0;
display: inline-block;
width: 38vw;
height: 100vh;
background-color: #cfff00;
}
#indexyellowright{
position: fixed;
left: 76vw;
top: 0;
display: inline-block;
height: 100vh;
width: 24vw;
background-color: #cfff00;
}
.indextext{
position: fixed;
z-index: 2;
}
a.indexdt{
font-weight: 400;
}

@ -1,449 +0,0 @@
@font-face {
font-family: "Lyon";
src: url("LyonJeanTrue.ttf");
font-weight: 300;
font-style: normal;}
@font-face {
font-family: "Favorit";
src: url("Favorit_Regular.ttf");
font-weight: 300;
font-style: normal;}
@font-face {
font-family: "Favorit";
src: url("Favorit_Regular-Italic.ttf");
font-weight: 300;
font-style: italic;}
@font-face {
font-family: "Favorit";
src: url("Favorit_Medium.ttf");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: "Favorit";
src: url("Favorit_Medium-Italic.ttf");
font-weight: 400;
font-style: italic;}
body {
background-color: #e6e7e8;
overflow-x: hidden;
width: 100vw;
}
.spaceleft{
margin-left: 15vw;
padding-top: 30px;
padding-left: 15px;
}
h3{
font-weight: 400;
margin-bottom: 20px;
text-transform: uppercase;
transform: scaleX(0.75);
transform-origin: 0 0;
font-size: calc(10px + 0.3vw);
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
h4{
font-weight: 400;
margin-bottom: 5px;
text-transform: uppercase;
transform: scaleX(0.75);
transform-origin: 0 0;
font-size: calc(10px + 0.3vw);
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
a{
color: #000;
text-decoration: none;
display: inline;
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-weight: 300;
}
a:hover{
color: #cfff00;
text-decoration: none;
cursor: pointer;
}
a:visited{
text-decoration: none;
}
/* ASIDE */
aside{
position: fixed;
top: 0;
left: 0;
width: calc(15vw - 30px);
height: 100vh;
z-index: 2;
display: inline-block;
background-color: #cfff00;
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-size: calc(10px + 0.3vw);
font-weight: 400;
font-style: normal;
line-height: 110%;
padding-left: 30px;
padding-top: 30px;
}
li{
transform: scaleX(0.75);
transform-origin: 0 0;
}
h2{
transform: scaleX(0.75);
transform-origin: 0 0;
font-weight: 400;
}
a.mapping:hover{
color: #FFF;
text-decoration: none;
cursor: pointer;
}
/* INDEX */
h1{
color: #FFF;
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(15px + 5vw);
text-align: center;
width: 100vw;
padding-bottom: 15px;
}
#indexabout{
padding-top: 20vh;
padding-bottom: 25px;
}
dl{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-size: calc(12px + 0.3vw);
text-align: center;
width: 100vw;
font-weight: 400;
font-style: italic;
transform: scaleX(0.75);
line-height: 110%;
}
.colorbackground{
margin-top: -5px;
position: absolute;
overflow: hidden;
width: 100vw;
height: 100vh;
z-index: 1;
}
#indexyellowleft{
position: fixed;
left: 0;
top: 0;
display: inline-block;
width: 38vw;
height: 100vh;
background-color: #cfff00;
}
#indexyellowright{
position: fixed;
left: 76vw;
top: 0;
display: inline-block;
height: 100vh;
width: 24vw;
background-color: #cfff00;
}
.indextext{
position: fixed;
z-index: 2;
}
/* HEADER */
header{
position: fixed;
top: 5px;
width: calc(100vw - 15px);
font-size: 12px;
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-weight: 300;
font-style: normal;
z-index: 999;
}
.marquee {
position: relative;
width: calc(100vw - 15px);
max-width: 100%;
overflow-x: hidden;
height: 50px;
}
.track {
position: absolute;
white-space: nowrap;
will-change: transform;
animation: marquee 20s linear infinite;
}
@keyframes marquee {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
a.head{
color: #FFF;
text-decoration: none;
display: inline;
font-family: "Lyon", Arial, Helvetica, sans-serif;
}
a.head:hover{
text-decoration: none;
cursor: pointer;
}
a.head:visited{
text-decoration: none;
/* BOOKS REQUESTS */
.requestabook{
position: fixed;
top: 0;
left: 80vw;
width: calc(20vw - 30px);
height: 100vh;
z-index: 3;
display: inline-block;
background-color: #cfff00;
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-size: calc(10px + 0.3vw);
font-weight: 300;
font-style: normal;
line-height: 110%;
padding-left: 30px;
padding-top: 30px;
}
.scrollrequests{
overflow: auto;
height: 100%;
}
.booksrequested{
padding-bottom: 15px;
padding-top: 15px;
padding-left: 5px;
}
.info{
transform: scaleX(0.75);
transform-origin: 0 0;
}
a.linktorequest{
text-decoration: none;
font-style: italic;
display: inline;
margin-bottom: 15px;
}
a.linktorequest:hover{
color: #FFF;
text-decoration: none;
cursor: pointer;
}
@keyframes blinker {
50% {
opacity: 0.5;
}
}
.compressed{
animation: blinker 1s linear infinite;
transform: scaleX(0.75);
transform-origin: 0 0;
padding-top: 10px;
padding-bottom: 15px;
}
/* UPLOAD A BOOK */
.watermarkspace{
padding-top: 30px;
}
.uploadspace{
padding-top: 30px;
}
.form-group{
padding-bottom: 15px;
}
.finalbutton{
margin-top: 10px;
}
button{
border-top: 2px solid white;
border-left: 2px solid white;
border-right: 2px solid black;
border-bottom: 2px solid black;
padding-bottom: 1px;
transform-origin: 0 0;
font-family: "Favorit", Arial, Helvetica, sans-serif;
text-transform: uppercase;
}
label {
line-height: 120%;
}
input{
margin-top: 5px;
}
form{
margin-left: 40px;
display: inline-block;
}
.explainspace{
width: 320px;
display: inline-block;
vertical-align:top;
font-style: italic;
}
.secondp{
text-indent: 30px;
}
/* TOR BROWSER */
img{
height: 300px;
}
.cover{
display: inline-block;
vertical-align: top;
}
figcaption{
font-weight: 400;
margin-bottom: 20px;
text-transform: uppercase;
transform: scaleX(0.75);
transform-origin: 0 0;
font-size: calc(7px + 0.3vw);
}
/* TEXT ABOUT */
.indentedblock{
padding-left: 15px;
padding-bottom: 30px;
}
h5{
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(15px + 0.3vw);
}
.aboutparagraph{
font-family: "Favorit", Arial, Helvetica, sans-serif;
width: 600px;
padding-bottom: 15px;
font-size: calc(10px + 0.3vw);
font-weight: 300;
font-style: normal;
}
.aboutlastparagraph{
width: 600px;
padding-bottom: 50px;
font-size: calc(10px + 0.3vw);
font-weight: 300;
font-style: normal;
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
/* GUIDELINES */
.subfour{
transform: scaleX(0.65);
padding-bottom: 20px;
}
blockquote{
width: 600px;
padding-bottom: 30px;
font-size: calc(10px + 0.3vw);
font-style: italic;
padding-top: 5px;
transform: scaleX(0.85);
transform-origin: 0 0;
font-weight: 300;
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
dd{
font-family: "Favorit", Arial, Helvetica, sans-serif;
}
.termslastparagraph{
width: 600px;
padding-bottom: 25px;
font-size: calc(10px + 0.3vw);
}
dd{
line-height: 115%;
padding-bottom: 5px;
width: 600px;
font-size: calc(10px + 0.3vw);
font-weight: 300;
}
.bulletnumber{
font-family: "Lyon", Arial, Helvetica, sans-serif;
font-size: calc(10px + 0.3vw);
}
p{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-weight: 300;
}
label{
font-family: "Favorit", Arial, Helvetica, sans-serif;
font-weight: 300;
}
.explainspace{
font-size: calc(8px + 0.25vw);
line-height: 110%;
}

@ -12,8 +12,8 @@
<dl> <dl>
<dt id="indexabout">ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion</dt> <dt id="indexabout">ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion</dt>
</dl> </dl>
<h1>404</h1>
<h1>TACTICAL WATERMARKS<br>ON TOR BROWSER!<br>404</h1> <h1>TACTICAL WATERMARKS<br>ON TOR BROWSER!</h1>
</div> </div>

@ -13,7 +13,7 @@
<dt id="indexabout">ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion</dt> <dt id="indexabout">ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion</dt>
</dl> </dl>
<h1>TACTICAL WATERMARKS<br>ON TOR BROWSER!<br>500</h1> <h1>TACTICAL WATERMARKS<br>ON TOR BROWSER!</h1>
</div> </div>

@ -1,90 +1,14 @@
{% extends "public/templates/public_template.html" %} {% extends "public/templates/public_template.html" %}
{% block title %}ABOUT TACTICAL WATERMARKS{% endblock %} {% block title %}ABOUT TACTICAL WATERMARKS{% endblock %}
{% block main %} {% block main %}
<div class="spaceleft aboutleft"> <div class="spaceleft">
<h3>About</h3> <h3>What is Tactical Watermarks</h3>
<h4>The Project</h4>
<h5>What is Tactical Watermarks?</h5><br> <h4>Each Step</h4>
<h4>The thesis</h4>
<p class="aboutparagraph">Tactical Watermarks, is an online republishing platform. I actively make use of digital watermarks as a means to explore topics such as anonymity, paywalls, archives, and provenance. While the primary intention of analogue watermarks was to leave traces of authenticity, marks of quality or even aesthetic enhancements, digital watermarks are being used as a way to create accountability for users. Through this platform, I describe and document ways of living within and resist a culture of surveillance in the realm of publishing.</p> <h4>Why on Tor Browser?</h4>
<p class="aboutparagraph">I am motivated by all the invisible individuals behind extra-legal publishing platforms, from curators, the ones who host, upload and even download material. Through the act of watermarking, I embed layers of information often dissolved within the processes of sharing texts. I experiment on how the process of adding stains can be twisted and revived. Stains are what I call user patches or marks that are difficult to remove and that do not play an active role in archives.</p>
<p class="aboutlastparagraph">In this platform, users can upload and request different titles. While talking with members from the Library Genesis forum, I understood the need to create a tool that allows people to share watermarked pdfs in a safe way. My platform is NOT a library, and it is also NOT an archive. I don't keep the files or intend to archive them. What I open is a space to de-watermark files, and append new anonymous watermarks with the technical and personal regards around sharing specific texts. In the end, these stories will circulate alongside the main narrative. With python, I will automate a republishing stream that enables me to automatically spread these unique files to Library Genesis.</p>
<h5>The Project</h5><br>
<p class="aboutparagraph">Strategies such as watermarking are used by companies to discourage the distribution of proprietary material, making users more liable and accountable for their action. Therefore, customers are not able to share files they have paid for. With Tactical Watermarks I explore established reactive measures that help users evade surveillance in publishing. At the same time, I question how we can tackle this problem through the reappropriation of digital watermarks.</p>
<p class="aboutparagraph">Tactical Watermarks is a free web service where users can upload watermarked PDFs and ePUBs. I de-watermark the files and republished them to Lib Gen. I am removing in-text visible watermarks, but also editing watermarks present in the files metadata.</p>
<p class="aboutparagraph">Tactical Watermarks, is motivated by all the invisible individuals behind alternative publishing platforms, from curators, the ones who host, upload and even download material. With my creative response, I intended to create one more tactic to bypass surveillance in the publishing realm. Though, it does not try to be the foolproof answer to opening access to published material. It is reassuring to feel that a wide variety of infrastructures, from shadow libraries to online digital archives already exist as temporary solutions to the main problematic. It is also comforting that users display daily acts of voluntary resistance amongst them, from researchers creating informal groups to share copyrighted material to users mirroring collections in attempts to extend their life span.My project starts focused on acknowledging the importance of informal communitiesof resistance and on the individuals that make this possible. Tactical Watermarks reflects on the social, political and cultural aspects behind the use of restrictive measuresin publishing. It is not a finished project, and it doesnt intend to be, it embraces that the possibilities of tactical watermarks will continue to reveal themselves throughthe extensive use of the tool.</p>
<p class="aboutlastparagraph">Researchers need to react against the organisations creating monopolies and closing access to published material. We need to build new online spaces where people can connect. Users need access to online forums where counterstrategies are widely available. We need to organise workshops and build communities to bypass the control of corporations only focused on the monetary outcome from research. It is important to continue sharing texts and opening access to our resources collectively. We need to mirror collections and produce new and unpredictable reactive actions against closed publishing streams. When it comesto opening access to paywalled material, a lot is yet to be done. Tactical Watermarks isa way to stimulate new reactive measures, embracing a positive discourse when it comesto subvert digital surveillance.</p>
<h5>Each Step</h5><br>
<div class="indentedblock">
<h4>De-watermark and Republish</h4>
<p class="aboutparagraph">In this route you can upload a title that will be republished to Library Genesis. We take care of the whole process of republishing. Books should not have watermarks. They will not be removed. We will also create a uploaders signature.</p>
<h4>Republish a new title</h4>
<p class="aboutparagraph">In this route you can upload a watermarked title that will be republished to Library Genesis. I will de-watermark your text and take care of the whole process of republishing. All watermarks will be removed. We will also create a uploaders signature.</p>
<h4>What is the uploaders signature</h4>
<p class="aboutparagraph">The uploaders signature is an anonymous watermarks with the technical and personal regards around sharing specific texts. In the end, these stories will circulate alongside the main narrative.</p>
<p class="aboutparagraph">Tactical Watermarks has the primary objective of creating a positive discourse around the act of watermarking. This discourse will enable the creation of a top layer of information, able to embed traces of provenance in different texts. By provenance, I intend to express all the trails not used to surveil users but the ones able to trace historical importance to files and that facilitate precise documentation within an archive or library.</p>
<p class="aboutparagraph">The uploaders signature challenges centralised distribution channels and wonderes on how the process of adding stains can be twisted and revived. Stains are what I will call user patches or marks that are difficult to remove and that do not play an active role in archives. While exploring the process of adding imprints, different uses arose: as a way to obscure previous ones, of commenting on the situation and encouraging behaviours, to create relations and communities, augmenting the sense of solidarity in archives, for digital enhancements, marks of quality, etc.</p>
<p class="aboutlastparagraph">Tactical Watermarks mayform a discourse around topics such as anonymity, borders, archives, and provenance.While rethinking watermarks, I explore their hidden layers and aspects of surprise, visibility or invisibility, on different forms of communication. It is essential to acknowledgethat watermarks have the power to infiltrate, perform different roles and create parallel streams of information within various texts. When it comes to publishing, Tactical Watermarks create a critical discourse around the right to access knowledge and represent the ones that fight for it!</p>
</div>
<h5>Batch upload</h5><br>
<p class="aboutlastparagraph">If you want to batch upload, please <a href="mailto:butlerbeauregard@protonmail.com">contact me</a> directly!</p>
<h5>Request a book</h5><br>
<p class="aboutparagraph">In Tactical Watermarks I have created a space where users can request new titles. This option increases the sociability within the web platform and also augments the sense of community and solidarity that exists in this online space.</p>
<p class="aboutlastparagraph">Requesting a new title is also an approach to populate Library Genesis with files that might be missing to other users of this shadow-library aswell.</p>
<h5>Tactical Watermarks Guidelines</h5><br>
<p class="aboutlastparagraph">Read the terms <a href="terms">here</a>!</p>
<h5>The thesis</h5><br>
<p class="aboutlastparagraph">READ THE FULL THESIS ON TACTICAL WATERMARKS <a href="https://pzwiki.wdka.nl/mw-mediadesign/images/6/6f/Tactical_Watermarks_Pedro_Sa_Couto_0972575.pdf">HERE!</a></p>
<h5>Why releasing an onion version?</h5><br>
<p class="aboutlastparagraph">The access through Tor protocol to Tactical Watermarks allows users to access the web aplication through a .onion top-level domain. The onion address establishes a higher level of protection to users of the platform. Releasing this version is also a generous act regarding all the intervinients that want to get involved with a higher standard of anonymity.</p>
<h5>Colophon</h5><br>
<div class="indentedblock">
<h4>Author</h4>
<p class="aboutparagraph">Mr. Beauregard</p>
<p class="aboutparagraph">This work has been produced in the context of the graduation research of Mr. Beauregard from the Experimental Publishing (XPUB) Master course at the Piet Zwart Institute,Willem de Kooning Academy, Rotterdam University of Applied Sciences.</p>
<p class="aboutparagraph">XPUB is a two year Master of Arts in Fine Art and Design that focuses on the intents,means and consequences of making things public and creating publicsin the age of post-digital networks.https://xpub.nl.</p>
<p class="aboutparagraph">This publication is based on the graduation thesis Tactical Watermarks,written under the supervision of Marloes de Valk.</p>
<h4>License</h4>
<p class="aboutparagraph">Copyleft: This is a free work. You can copy, distribute, and modify it underthe terms of the Free Art License http://artlibre.org/licence/lal/en/</p>
</div>
</div> </div>
{% endblock %} {% endblock %}

@ -9,7 +9,7 @@
{% for cover in covers %} {% for cover in covers %}
<div class="cover"> <div class="cover">
<img src=".{{ url_for('static', filename='covers/' + cover) }}"></img> <img src="{{ url_for('static', filename='covers/' + cover) }}"></img>
<figcaption><a href="{{ url_for('static', filename='covers/' + cover) }}">{{ cover }}</a></figcaption> <figcaption><a href="{{ url_for('static', filename='covers/' + cover) }}">{{ cover }}</a></figcaption>
</div> </div>
{% endfor %} {% endfor %}

@ -10,16 +10,16 @@
<div class="indextext"> <div class="indextext">
<dl> <dl>
<dt id="indexabout"><a href="about" class="indexdt">About Tactical Watermarks</a></dt> <dt id="indexabout"><a href="about">About Tactical Watermarks</a></dt>
</dl> </dl>
<h1>TACTICAL WATERMARKS</h1> <h1>TACTICAL WATERMARKS</h1>
<dl> <dl>
<dt><a href="uploadbook" class="indexdt" >De-watermark and republish a title</a></dt> <dt><a href="uploadbook">De-watermark and republish a title</a></dt>
<dt><a href="republish" class="indexdt">Republish a new title</a></dt> <dt><a href="republish">Republish a new title</a></dt>
<dt><a href="terms" class="indexdt">Community Guidelines</a></dt> <dt><a href="terms">Read Terms & Conditions</a></dt>
<dt><a href="ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion" class="indexdt">Link to Tor Browser</a></dt> <dt><a href="ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion">Link to Tor Browser</a></dt>
</dl> </dl>
</div> </div>

@ -9,7 +9,7 @@
<div class="explainspace"> <div class="explainspace">
<p>Here you can upload a file that will be republished to Library Genesis. We take care of the whole process of republishing. Your book should not have watermarks. They will not be removed.</p> <p>Here you can upload a file that will be republished to Library Genesis. We take care of the whole process of republishing. Your book should not have watermarks. They will not be removed.</p>
<p class="secondp">We will also create a uploaders signature, read more about it <a href="about">here</a>! Please feel free to leave your remarks on the process of sharing the file. If you want to batch upload, please <a href="mailto:butlerbeauregard@protonmail.com">contact me</a> directly!</p> <p class="secondp">We will also create a uploaders signature, read more about it <a href="about">here</a>! Please feel free to leave your remarks on the process of sharing the file. If you want to batch upload, please <a href="mailto:pedrosacouto@protonmail.com">contact me</a> directly!</p>
</div> </div>
<form action="uploadbook" method="POST" enctype="multipart/form-data"> <form action="uploadbook" method="POST" enctype="multipart/form-data">
@ -57,7 +57,7 @@
</div> </div>
<div class="uploadspace"> <div class="uploadspace">
<input type="checkbox" name="match-with-pairs"></input><a href="terms">Agree with the Guidelines</a><br> <input type="checkbox" name="match-with-pairs">Agree with the T&C</input><br>
<button type="submit" class="finalbutton"> Upload </button> <button type="submit" class="finalbutton"> Upload </button>
</div> </div>

@ -7,7 +7,7 @@
<h3>Request a Book</h3> <h3>Request a Book</h3>
<form action='submit' method='post'> <form action='/submit' method='post'>
<label for='title'>Title</label> <label for='title'>Title</label>
<input name='title' type='text'></input> <input name='title' type='text'></input>

@ -5,11 +5,11 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" href=".{{ url_for('static', filename='img/beau.png') }}"> <link rel="icon" href="{{ url_for('static', filename='img/beau.png') }}">
<meta name="date" content="JULY 2020"> <meta name="date" content="JULY 2020">
<link rel="stylesheet" href=".{{ url_for('static', filename='css/reset.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/reset.css') }}">
<link rel="stylesheet" href=".{{ url_for('static', filename='css/style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src=".{{ url_for('static', filename='js/app.js') }}"></script> <script src="{{ url_for('static', filename='js/app.js') }}"></script>
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
</head> </head>
@ -18,7 +18,7 @@
<div class="leftmarquee"> <div class="leftmarquee">
<div class="marquee"> <div class="marquee">
<div class="track"> <div class="track">
<div class="content"><a class="head" href="/watermark">TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS</a></div> <div class="content"><a class="head" href="">TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS</a></div>
</div> </div>
</div> </div>
</div> </div>

@ -6,10 +6,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="date" content="JULY 2020"> <meta name="date" content="JULY 2020">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href=".{{ url_for('static', filename='css/reset.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/reset.css') }}">
<link rel="stylesheet" href=".{{ url_for('static', filename='css/style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src=".{{ url_for('static', filename='js/app.js') }}"></script> <script src="{{ url_for('static', filename='js/app.js') }}"></script>
<link rel="icon" href=".{{ url_for('static', filename='img/beau.png') }}"> <link rel="icon" href="{{ url_for('static', filename='img/beau.png') }}">
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
</head> </head>
@ -18,7 +18,7 @@
<div class="leftmarquee"> <div class="leftmarquee">
<div class="marquee"> <div class="marquee">
<div class="track"> <div class="track">
<div class="content"><a class="head" href="/watermark">TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS</a></div> <div class="content"><a class="head" href="">TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS TACTICAL WATERMARKS</a></div>
</div> </div>
</div> </div>
</div> </div>
@ -31,7 +31,7 @@
<li><a class="mapping" href="about">↘About Tactical Watermarks</a></li> <li><a class="mapping" href="about">↘About Tactical Watermarks</a></li>
<li><a class="mapping" href="uploadbook">↘De-watermark and republish</a></li> <li><a class="mapping" href="uploadbook">↘De-watermark and republish</a></li>
<li><a class="mapping" href="republish">↘Republish</a></li> <li><a class="mapping" href="republish">↘Republish</a></li>
<li><a class="mapping" href="terms">Community Guidelines</a></li> <li><a class="mapping" href="terms">Read Terms & Conditions</a></li>
<li><a class="mapping" href="404">↘Link to Tor Browser</a></li> <li><a class="mapping" href="404">↘Link to Tor Browser</a></li>
</ul> </ul>
</aside> </aside>

@ -1,111 +1,18 @@
{% extends "public/templates/public_template.html" %} {% extends "public/templates/public_template.html" %}
{% block title %}GUIDELINES{% endblock %} {% block title %}TERMS AND CONDITIONS{% endblock %}
{% block main %} {% block main %}
<div class="spaceleft aboutleft"> <div class="spaceleft">
<h5>Tactical Watermarks Guidelines</h5><br><br> <h3>TERMS AND CONDITIONS</h3>
<p class="aboutparagraph">These guidelines clarify the values and methods of Tactical Watermarks, what you can expect from us and what we expect from users. The rules apply to the platform hosted on https://hub.xpub.nl/watermark/, where you are most likely reading this. If you prefer, Tactical Watermarks is also on Tor browser: http://ov73e3lxezo2klxva2frlzqbb2usiozqbe56xiochvz5lznpkk6kw4ad.onion/</p>
<p class="aboutparagraph">We don't intend or guarantee full availability and performance.</p>
<p class="termslastparagraph">The platform doesn't call for a lot of interactions between users, nonetheless, it is making things public and every user should be aware of the implications of such action. Tactical Watermarks is online and for you to use, but we ask you to consider the labour behind the files you're uploading and the resources you are using. This is not an archive nor a library. This is a platform to republish files, reflecting on provenance, privilege and publishing streams. Be deliberate with your choices and conscious of the guidelines.</p><br><br>
<h4><span class="bulletnumber">1.</span> Building the frame</h4>
<blockquote>Modular craftsman specialized in making the wooden screens known as "modularo". The screen or module is made-up of a wooden framework, on which a dense wire mesh is placed and also a movable wooden frame or deckle. It must be constructed so that it will support the weight of the paste and the water without deforming the paper.</blockquote>
<h4 class="subfour">We define Tactical Watermarks as:</h4>
<div class="indentedblock">
<p class="aboutparagraph">An online de-watermarking/republishing platform with no registration required. In Tactical Watermarks, we will de-watermarked and republish files uploaded by users to Library Genesis. We actively make use of digital watermarks as a means to explore topics such as anonymity, paywalls, archives, and provenance. While the primary intention of analogue watermarks was to leave traces of authenticity, marks of quality or even aesthetic enhancements, digital watermarks are being used as a way to create accountability for users. Through this platform, I describe and document ways of living within and resist a culture of surveillance in the realm of publishing.</p>
</div>
<h4 class="subfour">We define Artisan as:</h4>
<div class="indentedblock">
<dd>1. People without access to paid online archives and libraries, such as JSTOR, Elsevier, Verso Books, and others, who have access through a college, university, secondary school, public library, museum, foundation, government agency, research centre, corporate/for-profit organization or scholarly society (“Institutional Licensee”).</dd>
<dd>2. People who use Tactical Watermarks directly for asking new titles.</dd>
<dd>3. People who are interested in uncovering the processes behind republishing texts.</dd>
<dd>4. Invisible individuals behind extra-legal publishing platforms, curators, the ones who host, upload and even download material.</dd>
<dd>5. People that want to de-watermark PDFs and EPUBs.</dd>
<div>
<h4>The Project</h4>
<p>Here you will read the TOS</p>
</div> </div>
<h4><span class="bulletnumber">2.</span> Becoming an artisan</h4>
<blockquote>Papermaking in Italy is dominated by the historic and powerful feudal family, Fabriano. The Council Statute of 1436 prohibited anyone within a radius of 50 miles from Fabriano buildings from manufacturing paper or teaching paper making secrets to those not residing within the Council territory, pending a fine of 50 ducats. A later prohibition has even stiffer penalties. Transgressors were considered "rebels" and thereby banned from the city with consequent capital confiscation.</blockquote>
<h4 class="subfour">As an Artisan you:</h4>
<div class="indentedblock">
<dd>Publish content you own which doesn't infringe copyright laws.</dd>
<dd>Publish original content.</dd>
<dd>Are aware of the request list before you ask for the same file.</dd>
<dd>Request any kind of content.</dd>
<dd>Use the form to ask for files, and only for that.</dd>
<dd>Look at the request list and if you can help, you upload the needed content.</dd>
<dd>Remain anonymous.</dd>
</div>
<h4 class="subfour">You are prohibited to:</h4>
<div class="indentedblock">
<dd>Profit.</dd>
<dd>Demonstrate your identity — You must always stay anonymous.</dd>
<dd>Distribute active malware or exploits — Being part of a community includes not taking advantage of other members of the community.</dd>
</div>
<h4><span class="bulletnumber">3.</span> Gathering the pulp</h4>
<blockquote>Fabriano was the first manufacturing center to harness water power to drive the fibrillation (pulping) process, previously a labor intensive manual activity.</blockquote>
<p class="aboutparagraph">All the texts will automatically be republished to LibGen. In Library Genesis theres no score to maintain, necessary log-in, or price to pay.</p>
<p class="aboutparagraph">Library Genesis regularly fights against shut-down attempts. Strategies to increase the lifespan of the collection are put in place, such as encouraging the creation of mirrors. Mirrors allow hosting voluntary copies of entire collections or parts of them over different servers and points of access, making these more challenging to control.</p>
<p class="aboutparagraph">If you can, please mirror the collection or part of it.</p>
<p class="termslastparagraph">While researchers bump into expensive paywalls that were unaffordable for many, tactics such as shadow-libraries and online archives are put together to make research widely available. These online spaces provide areas to access media from alternative channels.</p>
<h4><span class="bulletnumber">4.</span> Living within libraries</h4>
<blockquote>After the whole process, the book starts circulating: entering small private libraries, kept in shelves in public spaces, rotating between hands. The artisan loses control of the pages, but the watermarks remain.</blockquote>
<h4>We are all responsible for enforcing the rules.</h4>
<p class="aboutparagraph">If you don't follow the guidelines when requesting a title, the comment will be deleted.</p>
<p class="termslastparagraph">We will not know, collect or control what you'll publish. If you choose to publish anything outside the guidelines, such as copyrighted material, this is your responsibility.</p>
<h4 class="subfour">We give you support.</h4>
<p class="aboutparagraph">For questions, comments, to talk or anything in between contact me, Mr. Beauregard at <a href="mailto:butlerbeauregard@protonmail.com">butlerbeauregard(at)protonmail(dot)com</a></p>
<p class="termslastparagraph">These guidelines will change every time it's needed. Last updated on 15 June 2020.</p>
</div>
<div class="requestabook"> <div class="requestabook">
<h2>LEAVE A COMMENT</h2> <h2>LEAVE A COMMENT</h2>

@ -9,7 +9,7 @@
<div class="explainspace"> <div class="explainspace">
<p>Here you can upload a watermarked file that will be republished to Library Genesis. I will de-watermark your text and take care of the whole process of republishing. All watermarks will be removed.</p> <p>Here you can upload a watermarked file that will be republished to Library Genesis. I will de-watermark your text and take care of the whole process of republishing. All watermarks will be removed.</p>
<p class="secondp">We will also create a uploaders signature, read more about it <a href="about">here</a>! Please feel free to leave your remarks on the process of sharing the file. If you want to batch upload, please <a href="mailto:butlerbeauregard@protonmail.com">contact me</a> directly!</p> <p class="secondp">We will also create a uploaders signature, read more about it <a href="about">here</a>! Please feel free to leave your remarks on the process of sharing the file. If you want to batch upload, please <a href="mailto:pedrosacouto@protonmail.com">contact me</a> directly!</p>
</div> </div>
<form action="uploadbook" method="POST" enctype="multipart/form-data"> <form action="uploadbook" method="POST" enctype="multipart/form-data">
@ -56,7 +56,7 @@
</div> </div>
<div class="uploadspace"> <div class="uploadspace">
<a href="terms"><input type="checkbox" name="match-with-pairs">Agree with the Guidelines</input></a><br> <input type="checkbox" name="match-with-pairs">Agree with the T&C</input><br>
<button type="submit" class="finalbutton"> Upload </button> <button type="submit" class="finalbutton"> Upload </button>
</div> </div>

@ -7,7 +7,7 @@
<h3>LEAVE A COMMENT</h3> <h3>LEAVE A COMMENT</h3>
<form action='submitcomment' method='post'> <form action='/submitcomment' method='post'>
<label for='name'>Name</label> <label for='name'>Name</label>
<input name='name' type='text'></input> <input name='name' type='text'></input>

@ -15,7 +15,6 @@ app.secret_key = 'PiracyIsCool'
now = datetime.datetime.now() now = datetime.datetime.now()
@app.route('/test', methods=['GET']) @app.route('/test', methods=['GET'])
def test(): def test():
index = url_for('index') index = url_for('index')
@ -24,6 +23,7 @@ def test():
return links return links
@app.route('/', methods=['GET']) @app.route('/', methods=['GET'])
def index(): def index():
return render_template("public/index.html") return render_template("public/index.html")
@ -34,11 +34,11 @@ def about():
# UPLOAD FILES # UPLOAD FILES
# THIS SHOULD BE IN CONFIG # THIS SHOULD BE IN CONFIG
app.config["BOOK_UPLOAD_DEWATERMARK"] = "/var/www/TacticalApp/app/static/dewatermark" app.config["BOOK_UPLOAD_DEWATERMARK"] = "app/static/dewatermark"
app.config["BOOK_UPLOAD_REPUBLISH"] = "/var/www/TacticalApp/app/static/republish" app.config["BOOK_UPLOAD_REPUBLISH"] = "app/static/republish"
app.config["BOOK_REQUEST"] = "/var/www/TacticalApp/app/static/request" app.config["BOOK_REQUEST"] = "app/static/request"
app.config["ALLOWED_BOOK_EXTENSIONS"] = ["PDF", "EPUB"] app.config["ALLOWED_BOOK_EXTENSIONS"] = ["PDF", "EPUB"]
#app.config["MAX_BOOK_FILESIZE"] = 4000 * 1024 * 1024 app.config["MAX_BOOK_FILESIZE"] = 500000000
def allowed_book(filename): def allowed_book(filename):
if not "." in filename: if not "." in filename:
@ -51,11 +51,11 @@ def allowed_book(filename):
else: else:
return False return False
#def allowed_book_filesize(filesize): def allowed_book_filesize(filesize):
# if int(filesize) <= app.config["MAX_BOOK_FILESIZE"]: if int(filesize) <= app.config["MAX_BOOK_FILESIZE"]:
# return True return True
# else: else:
# return False return False
#Request a book #Request a book
#REQUEST IN DEWATERMARK #REQUEST IN DEWATERMARK
@ -121,9 +121,9 @@ def uploadbook():
if request.files: if request.files:
#request filesize #request filesize
#if not allowed_book_filesize(request.cookies.get("filesize")): if not allowed_book_filesize(request.cookies.get("filesize")):
# print("File exceeded maximum size") print("File exceeded maximum size")
# return redirect(request.url) return redirect(request.url)
#demand checkbox #demand checkbox
if not request.form.get('match-with-pairs'): if not request.form.get('match-with-pairs'):
@ -188,9 +188,9 @@ def republish():
if request.files: if request.files:
#request filesize #request filesize
#if not allowed_book_filesize(request.cookies.get("filesize")): if not allowed_book_filesize(request.cookies.get("filesize")):
# print("File exceeded maximum size") print("File exceeded maximum size")
# return redirect(request.url) return redirect(request.url)
#demand checkbox #demand checkbox
if not request.form.get('match-with-pairs'): if not request.form.get('match-with-pairs'):
@ -243,7 +243,7 @@ def republish():
print("file saved") print("file saved")
# flash("file saved") # flash("file saved")
return redirect(url_for('republish')) return redirect(request.url)
return render_template("public/republish.html") return render_template("public/republish.html")

@ -1,5 +1,5 @@
class Config(object): class Config(object):
SERVER_NAME = '10.0.0.105' # 'hub.xpub.nl/watermark' # SERVER_NAME = 'hub.xpub.nl/watermark'
DEBUG = True DEBUG = True
TESTING = False TESTING = False
SESSION_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True
@ -10,7 +10,6 @@ class ProductionConfig(Config):
class DevelopmentConfig(Config): class DevelopmentConfig(Config):
DEBUG = True DEBUG = True
SESSION_COOKIE_SECURE = False SESSION_COOKIE_SECURE = False
SERVER_NAME = '127.0.0.1' # 'hub.xpub.nl/watermark'
class TestingConfig(Config): class TestingConfig(Config):
TESTING = True TESTING = True

@ -1 +0,0 @@
/etc/nginx/sites-available/default

Binary file not shown.

@ -1 +0,0 @@
/etc/systemd/system/watermarks.service
Loading…
Cancel
Save