Compare commits

...

1834 Commits

Author SHA1 Message Date
Lorenzo Yario
83b644f0f5
Merge pull request #920 from vichan-devel/5.2.1
5.2.1 Release
2025-04-02 04:45:22 -05:00
Lorenzo Yario
953635f807
Delete static/banners/.gitkeep 2025-04-02 04:44:51 -05:00
Lorenzo Yario
5968118231
bugfix 2025-04-02 04:39:20 -05:00
Lorenzo Yario
03da3b8db0
bug fix 2025-04-02 04:27:38 -05:00
Lorenzo Yario
f27e5a6989
ensure premade ban reasons are passed 2025-04-02 04:04:08 -05:00
Lorenzo Yario
0866adc89f
styling for predefined ban reasons 2025-04-02 03:56:03 -05:00
Lorenzo Yario
5259f88262
Update config.php 2025-04-02 03:46:07 -05:00
Lorenzo Yario
87420966b2
kick doesn't seem all too bad anymore. Removed X/Bluesky test 2025-04-02 03:03:58 -05:00
Lorenzo Yario
8350645a70
we don't need kick it doesn't embed nicely 2025-04-02 02:52:44 -05:00
Lorenzo Yario
16a6112b5b
new embed stuff 2025-04-02 02:45:04 -05:00
Lorenzo Yario
9468c9d372
Add files via upload 2025-04-02 02:22:44 -05:00
Lorenzo Yario
8aa965b77f
Create .gitkeep 2025-04-02 02:22:26 -05:00
Lorenzo Yario
b08dbcff14
Delete static/banners 2025-04-02 02:22:15 -05:00
Lorenzo Yario
f90291faf0
Create banners 2025-04-02 02:21:31 -05:00
Lorenzo Yario
e67f3f94bf
Delete static/banners/defaultbanner.png 2025-04-02 02:20:16 -05:00
Lorenzo Yario
4244b0a86c
tidied slightly 2025-04-02 02:14:46 -05:00
Lorenzo Yario
ac3f69a7eb
jank? maybe but it fixes our current config.php 2025-04-02 02:12:50 -05:00
Lorenzo Yario
7bc1f67b4e
X 2025-04-02 00:34:45 -05:00
Lorenzo Yario
54f32bc75d
X 2025-03-30 21:54:28 -05:00
Lorenzo Yario
5f1598367c
Merge pull request #783 from perdedora/fix-poster-id
fix: wrong poster id for op in api
2025-03-16 02:59:08 -05:00
Weav
3987b2a25d
Merge branch 'master' into fix-poster-id 2025-03-15 17:18:22 +00:00
Lorenzo Yario
6ec0c17ac9
Update login.html #890 2025-02-08 22:28:53 -06:00
Lorenzo Yario
2c2d476cea
5.2.1 2025-02-08 22:27:21 -06:00
Lorenzo Yario
717795ddff
Update fileinfo.html #891 2025-02-08 22:26:17 -06:00
Lorenzo Yario
d1e57290e0
Update bug_report.yml 2025-02-02 23:07:01 -06:00
Lorenzo Yario
0c92315837
Create bug_report.yml 2025-02-02 23:03:47 -06:00
Lorenzo Yario
c026e85b3c
Delete .github/ISSUE_TEMPLATE/bug_report.md
yml
2025-02-02 23:03:35 -06:00
Lorenzo Yario
8d76087710
what did I break? 2025-02-02 23:02:41 -06:00
Lorenzo Yario
50d57a4464
Update bug_report.md 2025-02-02 23:01:48 -06:00
Lorenzo Yario
96099945b9
Update issue templates 2025-02-02 22:51:55 -06:00
Lorenzo Yario
8c6cf17a97
Delete .github/ISSUE_TEMPLATE/bug_report.md
failed
2025-02-02 22:43:03 -06:00
Lorenzo Yario
b3f0658594
Update issue templates 2025-02-02 22:42:08 -06:00
Lorenzo Yario
33efeda647
Merge pull request #886 from vichan-devel/RealAngeleno-patch-18
adding in perdedora's PR to the master branch
2025-02-02 22:24:36 -06:00
Lorenzo Yario
92096b43b8
adding in perdedora's PR to the master branch 2025-02-02 22:24:06 -06:00
Lorenzo Yario
f3cb2552ce
modify default captcha config to work out of the box 2025-01-03 00:25:31 -06:00
Lorenzo Yario
440e3126c9
Merge pull request #872 from vichan-devel/RealAngeleno-patch-17
modify themes to use numeric array #871
2024-12-30 17:20:08 -06:00
Lorenzo Yario
47cbbbc972
modify themes to use numeric array #871 2024-12-30 17:19:42 -06:00
Lorenzo Yario
74959aaed9
Merge pull request #868 from vichan-devel/RealAngeleno-captchafix
fix native captcha implementation
2024-12-26 22:30:48 -06:00
Lorenzo Yario
2d9e5009f8
fix typo 2024-12-26 22:28:21 -06:00
Lorenzo Yario
372784ecd2
Merge pull request #866 from vichan-devel/7.4-compatibility3
7.4 compatibility3
2024-12-23 12:18:35 -06:00
Lorenzo Yario
0f8a5fa926
continued 7.4 compatibility 2024-12-22 15:17:22 -06:00
Lorenzo Yario
0a870ebdb3
7.4 2024-12-22 15:05:16 -06:00
Lorenzo Yario
3b9b23035e
7.4 compatibility (updated) 2024-12-22 15:02:58 -06:00
Lorenzo Yario
40571f2001
7.4 compatibility 2024-12-22 14:59:12 -06:00
Lorenzo Yario
c4cd4d3c12
Update HttpDriver.php 2024-12-22 14:55:57 -06:00
Lorenzo Yario
00fc21322c
7.4 compatibility 2024-12-22 14:54:48 -06:00
Lorenzo Yario
6606c182b5
7.4 compatibility 2024-12-22 14:51:07 -06:00
Lorenzo Yario
58c2f095dc
7.4 compatibility 2024-12-22 14:49:27 -06:00
Lorenzo Yario
8cd4cae56e
Merge pull request #863 from vichan-devel/RealAngeleno-patch-16
continued php 7.4 compatibility
2024-12-22 14:44:20 -06:00
Lorenzo Yario
762a0edefd
continued 7.4 compatibility 2024-12-22 14:42:16 -06:00
Lorenzo Yario
c94ab113de
continued 7.4 backwards compatibility 2024-12-22 14:37:22 -06:00
Lorenzo Yario
32f0cb3a5f
Merge pull request #862 from vichan-devel/5.2.0-74compatibility
5.2.0 PHP 7.4 compatibility
2024-12-22 14:23:08 -06:00
Lorenzo Yario
2466a3d859
7.4 compatibility 2024-12-22 14:15:40 -06:00
Lorenzo Yario
f3f7c0c75c
7.4 compatibility 2024-12-22 14:13:37 -06:00
Lorenzo Yario
29ee5aeb1d
For 7.4 compatibility 2024-12-22 14:05:42 -06:00
Lorenzo Yario
6a22a51a72
Merge pull request #860 from vichan-devel/5.2.0-release
5.2.0 release
2024-12-22 11:11:31 -06:00
Lorenzo Yario
a9059fab66
Merge branch 'master' into 5.2.0-release 2024-12-20 17:40:59 -06:00
Lorenzo Yario
9d590eed2a
typo? 2024-12-20 15:08:24 -06:00
Lorenzo Yario
e7aa695775
2025 2024-12-20 15:04:30 -06:00
Lorenzo Yario
f419ae046c
replace captcha click me image 2024-12-20 14:59:46 -06:00
Lorenzo Yario
0ed3513e66
add youtu.be and voca.ro 2024-12-20 14:43:13 -06:00
Lorenzo Yario
a376a5a2e3
finish stripping current antispam system 2024-12-20 02:31:26 -06:00
Lorenzo Yario
b2ca26dba5
Merge pull request #858 from vichan-devel/removecurrentantibot
Remove current antibot system
2024-12-20 02:27:40 -06:00
Lorenzo Yario
6f5b0ae6d5
strip old antibot system 2024-12-20 02:24:18 -06:00
Lorenzo Yario
5f2f653993
Update functions.php 2024-12-20 02:16:59 -06:00
Lorenzo Yario
0ff0e707d6
remove vichan's current antibot system 2024-12-20 01:56:57 -06:00
Lorenzo Yario
26ffd1aa72
remove anti-bot functions 2024-12-20 01:08:41 -06:00
Lorenzo Yario
2e91c1ed3d
Update FileLogDriver.php 2024-12-20 00:24:46 -06:00
Lorenzo Yario
efd4810e83
Merge pull request #856 from vichan-devel/RealAngeleno-patch-15
skip captcha or log settings in mod.php config
2024-12-16 23:16:18 -06:00
Lorenzo Yario
9dacdf59b1
skip captcha or log settings in mod.php config
relates to multidimensional arrays
2024-12-16 23:15:23 -06:00
Lorenzo Yario
b889b10626
Merge pull request #834 from Zankaria/patch-2
Fix #830 remove multiple return types for PHP 7.4 support.
2024-10-31 13:52:09 -07:00
Zankaria
b5a9dc4d1a
bans.php: remove multiple return types for PHP 7.4 support 2024-10-31 14:47:11 +01:00
Lorenzo Yario
d6677bb90c
Merge pull request #825 from Zankaria/context-fix
context.php: fix missing include file
2024-10-20 12:03:51 -07:00
Lorenzo Yario
c88acfc4f0
Merge pull request #826 from vichan-devel/RealAngeleno-patch-13
minor bugfix relating to auth when changing your own username
2024-10-20 12:03:42 -07:00
Lorenzo Yario
58f7302936
minor bugfix relating to auth when changing your own username 2024-10-20 12:03:15 -07:00
Zankaria
76f6c721e9 context.php: fix missing include file 2024-10-16 22:49:19 +02:00
Lorenzo Yario
c1307feeb5
Merge pull request #818 from Zankaria/dep-inj-cache-wrap
Dependency injected cache
2024-10-15 20:40:34 -07:00
Lorenzo Yario
e65bfa87c4
Merge pull request #824 from Zankaria/inline-dice
Inline dices via markup
2024-10-15 20:40:21 -07:00
Zankaria
b67ff982e2 composer: add dice.php to autoload 2024-10-15 21:14:47 +02:00
Zankaria
fba88643ec config.php: add inline dice rolling markup support to the default configuration 2024-10-15 21:14:47 +02:00
Zankaria
ad1d56d092 dice.php: handle inline dice rolling markup 2024-10-15 21:14:44 +02:00
Zankaria
ceccbfc5b7 config.php: limit the number of dicerolls 2024-10-14 17:46:29 +02:00
Zankaria
b8c53fbbcd dice.php: extract email dice function from functions.php 2024-10-14 12:31:36 +02:00
Zankaria
27e4bd833a config.php: use op-cache friend array syntax for markup config 2024-10-14 12:18:04 +02:00
Zankaria
fe7a667441 style.css: add diceroll styling 2024-10-14 12:13:21 +02:00
Zankaria
115f28807a FsCacheDriver.php: collect expired cache items before operating on the cache 2024-10-10 23:10:05 +02:00
Zankaria
003e8f6d3b maintenance.php: delete expired filesystem cache 2024-10-10 23:10:05 +02:00
Zankaria
243e4894fa Use CacheDriver and Context for mod.php and mod pages 2024-10-10 23:10:05 +02:00
Zankaria
589435b667 context.php: use shared cache driver 2024-10-10 23:10:05 +02:00
Zankaria
f138b4b887 cache.php: wrap new cache drivers 2024-10-10 23:10:05 +02:00
Zankaria
ace2f2e83b driver: break up cache drivers 2024-10-10 23:10:05 +02:00
Zankaria
3d406aeab2 cache-driver.php: move to Data 2024-10-10 23:10:05 +02:00
Zankaria
66d2f90171 cache-driver.php: filesystem handle expired values. 2024-10-10 23:09:55 +02:00
Zankaria
5ea42fa0e2 config.php: update cache documentation 2024-10-10 22:56:56 +02:00
Zankaria
b57d9bfbb3 cache: implement cache locking for filesystem cache and give it multiprocess support 2024-10-10 22:56:56 +02:00
Zankaria
82ea1815fd Refactor cache driver 2024-10-10 22:56:56 +02:00
Lorenzo Yario
7c305f58bf
Merge pull request #822 from Zankaria/fix-captcha-call
post.php: fix invocation of native captcha
2024-10-08 20:12:25 -07:00
Lorenzo Yario
59d0dd9083
Merge pull request #821 from Zankaria/refactor-log
Break up the log subsystem and move it into Data
2024-10-08 20:12:13 -07:00
Lorenzo Yario
f60b4d190f
Merge pull request #789 from perdedora/expand-filename
Original filename changes
2024-10-08 20:11:49 -07:00
Lorenzo Yario
88a81a6d74
Merge pull request #819 from Zankaria/minor-format
Assorted PHP refactoring
2024-10-08 20:11:41 -07:00
Zankaria
3fe44653f2 post.php: fix invocation of native captcha 2024-10-06 13:08:29 +02:00
Zankaria
0e8909ac4e pages.php: fix whitespace indentation 2024-10-06 11:33:20 +02:00
Zankaria
767b8fd8c3 mod.php: add missing context parameter 2024-10-06 11:25:57 +02:00
Zankaria
f9127dd478 mod.php: $matches should always be an array 2024-10-06 11:25:11 +02:00
Zankaria
6c6ec65b02 pages.php: extract $mod array 2024-10-06 11:23:27 +02:00
Zankaria
23f3d15a52 extract create_pm_header 2024-10-06 10:41:32 +02:00
Zankaria
d88d6c814a docker: use shorter name for instance 2024-10-04 20:16:06 +02:00
Zankaria
65a668d3a8 composer.json: use classmap for LogDriver 2024-10-04 20:16:06 +02:00
Zankaria
b501852ea4 config.php: update LogDriver configuration 2024-10-04 20:16:06 +02:00
Zankaria
927a837216 post.php: update LogDriver 2024-10-04 20:16:06 +02:00
Zankaria
79af4b34dd context.php: update LogDriver 2024-10-04 20:16:06 +02:00
Zankaria
36d48951c1 log-driver.php: split up log driver 2024-10-04 20:16:04 +02:00
Zankaria
5dab17e5f4 log-driver.php: move to Data 2024-10-04 13:05:06 +02:00
Lorenzo Yario
c97c61aeca
Merge pull request #820 from Zankaria/http-refactor
Move HttpDriver to Data
2024-10-04 00:00:06 -07:00
Zankaria
59551a2042 composer.json: rely on classmap for HttpDriver 2024-10-04 01:21:21 +02:00
Zankaria
1682272f75 http-driver.php: rename to HttpDriver 2024-10-04 01:13:15 +02:00
Zankaria
3eed312b6b http-driver.php: minor refactor 2024-10-04 01:13:15 +02:00
Zankaria
cae85a6a0c http-driver.php: move to Data 2024-10-04 01:13:12 +02:00
Zankaria
25b2b6bc6e display.php: trim 2024-10-02 22:19:44 +02:00
Lorenzo Yario
7377885de9
Merge pull request #815 from Zankaria/remove-extensions
style.css: remove deprecated extensions
2024-10-02 08:33:02 -07:00
Lorenzo Yario
f421e25e63
Merge pull request #816 from Zankaria/fix-dir-config
Assorted php fixes
2024-10-02 08:32:52 -07:00
Zankaria
3e9ad58e97 config.php: fix mod config array 2024-10-01 23:54:16 +02:00
Zankaria
f4ff39c876 post.php, mod.php: pass the context to check_login 2024-10-01 22:16:54 +02:00
Zankaria
e6133ef00f auth.php: passthrough the context 2024-10-01 22:16:54 +02:00
Zankaria
13ca053e06 config.php: fix default 'dir' configuration 2024-10-01 22:16:54 +02:00
Zankaria
44b31eff0b style.css: remove deprecated extensions 2024-10-01 21:13:36 +02:00
Lorenzo Yario
785643a3bd
Merge pull request #814 from Zankaria/patch-1
docker: use composer LTS
2024-10-01 09:38:02 -07:00
Zankaria
e70c087f5f
docker: use composer LTS 2024-10-01 15:01:03 +02:00
Lorenzo Yario
428a686f47
fix minor exploit with banning 2024-09-21 14:39:13 -07:00
Lorenzo Yario
c95877bdcb
Merge pull request #803 from Zankaria/more-busting
More cache busting with resource_version
2024-09-20 18:45:14 -07:00
Lorenzo Yario
380ae8c675
Merge pull request #811 from Zankaria/main-js-let
Minor JS update
2024-09-20 18:42:01 -07:00
Lorenzo Yario
2f37b3ce51
Merge pull request #812 from Zankaria/anti-bot-format
Format anti-bot.php
2024-09-20 18:41:48 -07:00
Zankaria
65008dec98 anti-bot.php: remove unused variable 2024-09-19 23:13:42 +02:00
Zankaria
0e8aeca4af anti-bot.php: format 2024-09-19 23:09:02 +02:00
Zankaria
bdd7090e75 quote-selection.js: format 2024-09-19 22:58:23 +02:00
Zankaria
fd309443ea js: drop IE support 2024-09-19 22:54:04 +02:00
Zankaria
4332b70363 quote-selection.js: trim 2024-09-19 22:51:31 +02:00
Zankaria
cb6d6f13dd main.js: use let 2024-09-19 22:51:01 +02:00
Zankaria
6b60f841d4 template: supply data-resource-version to main.js 2024-09-19 22:28:55 +02:00
Zankaria
3c5484a7c2 main.js: load styles with dyanamically provided resource version.
This is done because:
 - If the version is updated before the rebuild, someone might cache the old version in the meanwhile.
 - One could not rebuild javascript before updating the version. Now it's possible.
2024-09-19 22:28:52 +02:00
Zankaria
fcf5c3d73a templates: bust all css caches with resource_version 2024-09-19 22:01:51 +02:00
Zankaria
9fbc816205 templates: bust all js caches with resource_version 2024-09-19 22:01:51 +02:00
Lorenzo Yario
bd5c2c61b9
Merge pull request #810 from vichan-devel/revert-809-howwwwww
i jinxed the previous commit
2024-09-19 01:33:18 -07:00
Lorenzo Yario
c1788d0792
Revert "revert trimming and this somehow fixes the antibot issues??????" 2024-09-19 01:32:49 -07:00
Lorenzo Yario
ccfcd03c95
Merge pull request #809 from vichan-devel/howwwwww
revert trimming and this somehow fixes the antibot issues??????
2024-09-19 01:28:18 -07:00
Lorenzo Yario
e1a4ae5336
revert trimming and this somehow fixes the antibot issues??????
idk but it works somehow??????
2024-09-19 01:26:50 -07:00
Lorenzo Yario
1effe1648b
add some spaces 2024-09-17 23:28:21 -07:00
Lorenzo Yario
36737b77a8
made https flag make sense 2024-09-17 22:20:36 -07:00
Lorenzo Yario
a457b905bf
from master branch 2024-09-17 21:44:06 -07:00
Lorenzo Yario
3291dc27f9
Merge pull request #788 from perdedora/patch-747
fixes #747
2024-09-17 21:40:04 -07:00
Lorenzo Yario
8c27b5261c
lazy loading commit 2024-09-17 21:18:09 -07:00
Lorenzo Yario
16bb704154
lazy loading commit 2024-09-17 21:15:43 -07:00
Lorenzo Yario
1db5c788dd
lazy loading 2024-09-17 21:03:05 -07:00
Lorenzo Yario
2b3eae89f1
Merge pull request #805 from perdedora/fix-oversights
Fix oversights
2024-09-17 21:01:53 -07:00
Lorenzo Yario
ce844b9270
Merge pull request #807 from seisatsu/dev
Fix typo in post.php that breaks Tesseract OCR
2024-09-17 21:00:51 -07:00
seisatsu
43b926c41b Fix typo in post.php that breaks Tesseract OCR
Fixes a typo in post.php that causes an uninitialized variable "$value"
to be referenced instead of the correct variable "$txt". This caused all
attempts to use the Tesseract OCR feature to fail with an error.
2024-09-06 15:23:37 -05:00
fowr
eeb55133eb
add missing context file to composer autoload 2024-08-25 17:01:31 -03:00
fowr
cd5c57f717
fix oversights introduced in captcha; 2024-08-25 17:01:06 -03:00
Lorenzo Yario
1672646213
Merge pull request #802 from Zankaria/resouce-ver-fix
Fix a couple of things with PR #801
2024-08-24 22:16:39 -07:00
Zankaria
6ea8fd5bf3 config.php: add missing default configuration, remove db settings 2024-08-21 14:05:29 +02:00
Lorenzo Yario
bf32a24b96
Merge pull request #798 from Zankaria/link-fallback
Add a fallback if link() fails
2024-08-20 23:36:56 -07:00
Lorenzo Yario
187f16693c
Merge pull request #801 from perdedora/resource_version
Resource version
2024-08-20 23:36:38 -07:00
fowr
13b587cf62
add resource_version to avoid cache. 2024-08-20 21:27:22 -03:00
Zankaria
1191dfb193 pages.php: add copy fallback in case of already existing file when moving thread. 2024-08-18 01:06:45 +02:00
Lorenzo Yario
5ee48c5865
Merge pull request #793 from Zankaria/captcha-rework-vichan
Refactor (again) the captcha backend + add support for dynamic captchas
2024-08-16 21:43:31 -07:00
Lorenzo Yario
60135bbb89
Merge pull request #794 from Zankaria/fix-di
Forgot to convert a method call in #784
2024-08-16 21:43:24 -07:00
Lorenzo Yario
39876f3cc7
Merge pull request #795 from Zankaria/api-modern
Modernize (a bit) the Api class
2024-08-16 21:43:17 -07:00
Lorenzo Yario
84a3bedd18
Merge pull request #796 from Zankaria/mod-use-di
Add the context dependency injection container to the mod pages
2024-08-16 21:43:07 -07:00
Lorenzo Yario
90dead0394
Merge pull request #797 from Zankaria/function-themes
Split the theme functions from functions.php
2024-08-16 21:42:43 -07:00
fowr
4f68166870 api.php: using depedency injection instead of globals 2024-08-16 19:26:19 +02:00
Zankaria
d408ed0413 theme.php: rename functions to snake_case 2024-08-16 18:33:02 +02:00
Zankaria
453ae795f5 composer.json: autoload theme.php 2024-08-16 18:24:48 +02:00
Zankaria
b2df2ab2a5 theme.php: extract theme functions from functions.php 2024-08-16 18:24:26 +02:00
Zankaria
81aebef2f4 pages.php: use modern array syntax for new empty arrays 2024-08-15 17:21:41 +02:00
Zankaria
b64bac5eb8 pages.php: use the context to access the configuration array 2024-08-15 17:13:43 +02:00
Zankaria
524ae94624 mod.php: pass the context to the mod pages 2024-08-15 17:13:34 +02:00
Zankaria
19082aec56 mod.php: use modern array syntax 2024-08-15 17:13:27 +02:00
Zankaria
e640217a8f post.php: fix DI method call 2024-08-15 16:39:12 +02:00
Zankaria
165ea5308a config.php: ops, wrong name for the native captcha 2024-08-15 16:33:56 +02:00
Zankaria
f7073d5d7e post.php: do not verify the poster IP if the captcha is dynamic 2024-08-15 16:22:58 +02:00
Zankaria
cb5fb68c5e header.html: format 2024-08-15 16:21:02 +02:00
Zankaria
fb92e5fb68 config.php: rework captcha configuration 2024-08-15 16:20:58 +02:00
Zankaria
a275d04efa captcha-queries.php: refactor NativeCaptchaQuery to use DI 2024-08-15 15:17:54 +02:00
Zankaria
933594194c captcha-queries.php: refactor remote captcha queries to use DI and abstract the implementation better 2024-08-15 15:11:32 +02:00
Zankaria
e825e7aac5 Add dynamic captcha support 2024-08-15 14:37:59 +02:00
fowr
d4b4cf5825
script to expand original filename if truncated 2024-08-12 15:35:16 -03:00
fowr
3e72171889
download original filename without javascript. 2024-08-12 15:34:48 -03:00
fowr
d8391eb34a
fixes #747 and also fix when loading next page on ukko wrong value. e.g >>thread_<cite_id> 2024-08-12 15:23:19 -03:00
Lorenzo Yario
e16dc142b7
Merge pull request #786 from Zankaria/config-opcache
Make configuration sub-arrays more opcache friendly
2024-08-11 17:03:17 -07:00
Lorenzo Yario
420ec4a852
Merge pull request #787 from Zankaria/mod-page
Unify mod page handlers
2024-08-11 17:02:57 -07:00
Zankaria
4d8a4db338 api.php: partially modernize the Api class 2024-08-11 16:14:03 +02:00
Zankaria
d1b06acbe9 mod.php: remove last mod_page_* handler, use only mod_* for mod pages 2024-08-11 15:45:24 +02:00
Zankaria
80be41f47a config.php: make config sub-arrays more opcache friendly 2024-08-11 15:39:21 +02:00
Lorenzo Yario
f3e81c80d9
Merge pull request #784 from Zankaria/micro-di
(What should be a) much better Dependency Injection implementation
2024-08-11 03:05:47 -07:00
Lorenzo Yario
b3ae38da57
Merge pull request #785 from Zankaria/batch-maintenance
Batch maintenance
2024-08-11 03:05:31 -07:00
Zankaria
51e0616eb8 bans.php: fix forgot to extract the mask 2024-08-11 12:04:12 +02:00
Zankaria
7e4acbb6d2 bans.php: FIX every IP matching to any ban that was going to expire eventually 2024-08-11 12:04:12 +02:00
Zankaria
ffe855222e bans.php: do not deserialize post that does not exist 2024-08-11 12:04:12 +02:00
Zankaria
1e0a95ce83 maintenance.php: fix and update logs 2024-08-11 12:04:12 +02:00
Zankaria
c4e3541b15 config.php: purge_bans configuration into the proper section 2024-08-11 12:04:12 +02:00
Zankaria
ede7591702 bans.php: refactor to expose the moratorium on ban deletion from the database.
Also fixes the 'purge_bans' configuration for non-cache deployments.
2024-08-11 12:04:12 +02:00
Zankaria
c057c6df29 functions.php: skip ban deletion on auto_maintenance disabled 2024-08-11 12:04:12 +02:00
Zankaria
4d97e69620 maintenance.php: add purging antispam to the tool 2024-08-11 12:04:12 +02:00
Zankaria
e5bbdb9d28 functions.php: make automated antispam puring optional 2024-08-11 12:04:12 +02:00
Zankaria
cc5e96eb9d bans.php: use modern array syntax 2024-08-11 12:04:12 +02:00
Zankaria
82b8eb1e74 bans.php: group deletion policy 2024-08-11 12:04:12 +02:00
Zankaria
2298d4433f bans.php: use modify inplace 2024-08-11 12:04:12 +02:00
Zankaria
accca93084 Add maintenance.php to the tools 2024-08-11 12:04:12 +02:00
Zankaria
cbaf19cb7a bans.php: make the purge configurable 2024-08-11 12:04:12 +02:00
Zankaria
75714505a0 config.php: add auto_maintenance configuration option 2024-08-11 12:04:10 +02:00
Zankaria
36476f6341 bans.php: split find implementations 2024-08-11 11:53:27 +02:00
Zankaria
980b2ef7bf bans.php: split findSingle implementations 2024-08-11 10:28:08 +02:00
Zankaria
e4707ee2a8 Delete stale unreferenced ban appeals via foreign key constrain 2024-08-11 10:20:02 +02:00
Zankaria
00cc1f434d anti-bot.php: add comments to _create_antibot 2024-08-11 10:17:14 +02:00
Zankaria
ee20bf574a functions.php: format _create_antibot 2024-08-11 10:14:54 +02:00
Zankaria
609da43548 anti-bot.php: trim 2024-08-11 10:13:44 +02:00
Zankaria
0c074016e7 context.php: much better Dependency Injection implementation 2024-08-11 10:06:20 +02:00
Weav
562ad74a12
Merge branch 'vichan-devel:master' into fix-poster-id 2024-08-09 14:16:42 -03:00
fowr
73fce5e571
fix: wrong poster id for op; 2024-08-09 14:10:18 -03:00
Lorenzo Yario
e5d423e595
revert column behavior 2024-08-09 00:43:43 -07:00
Lorenzo Yario
230cc252c5
add changes from #782 2024-08-09 00:39:08 -07:00
Lorenzo Yario
0fbf2f6f77
Merge pull request #781 from Zankaria/main-js-refactor
Refactor main.js
2024-08-08 23:41:29 -07:00
Lorenzo Yario
db20a350a1
Merge pull request #782 from perdedora/fix-cycle
fix: proper delete posts in a cyclical thread
2024-08-08 23:40:49 -07:00
fowr
7f45f31aa8
fix: proper delete posts in a cyclical thread 2024-08-06 11:49:51 -03:00
Zankaria
4445254b00 expand-video.js: onReady 2024-08-05 19:21:09 +02:00
Zankaria
85b03c0fb0 expand-video.js: format 2024-08-05 19:20:55 +02:00
Zankaria
d9a333a69f expand-all-images.js: onReady 2024-08-05 19:15:42 +02:00
Zankaria
e92e9469a8 expand-all-images.js: format 2024-08-05 19:15:26 +02:00
Zankaria
41f9aed606 inline-expanding-filename.js: onReady 2024-08-05 19:14:06 +02:00
Zankaria
5306f1d1f9 inline-expanding-filename.js: format 2024-08-05 19:14:04 +02:00
Zankaria
2749567c3f download-original.js: onReply 2024-08-05 19:11:32 +02:00
Zankaria
44e9a5aa57 download-original.js: format 2024-08-05 19:11:23 +02:00
Zankaria
5550bc4212 catalog-search.js: onReady 2024-08-05 19:09:05 +02:00
Zankaria
d9d05ddbf5 catalog-search.js: format 2024-08-05 19:08:55 +02:00
Zankaria
d9feb5cfa7 catalog.html: onReady 2024-08-05 19:03:24 +02:00
Zankaria
b7f46a239d show-backlinks.js: onReady 2024-08-05 19:01:27 +02:00
Zankaria
2728966c1c show-backlinks.js: format 2024-08-05 19:01:08 +02:00
Zankaria
ed46907a6c post-hover.js: onReady 2024-08-05 19:00:12 +02:00
Zankaria
31444d654a post-hover.js: format 2024-08-05 18:59:44 +02:00
Zankaria
6bea01b00b youtube.js: onReady 2024-08-05 18:50:35 +02:00
Zankaria
023e59d88f youtube.js: format 2024-08-05 18:50:23 +02:00
Zankaria
b822a76b23 style-select.js: onReply 2024-08-05 18:48:04 +02:00
Zankaria
902c558237 style-select.js: format 2024-08-05 18:47:53 +02:00
Zankaria
a018772267 show-backlinks.js: onReady 2024-08-05 18:38:38 +02:00
Zankaria
fa341b29d0 smartphone-spoiler.js: format 2024-08-05 18:38:35 +02:00
Zankaria
6daae3ec92 show-backlinks.js: onReady 2024-08-05 18:35:21 +02:00
Zankaria
da0f26485a show-backlinks.js: trim 2024-08-05 18:34:55 +02:00
Zankaria
8b773b124e main.js: rename onready to camelCase 2024-08-05 18:33:15 +02:00
Zankaria
c327a0439e main.js: rename init_stylechooser to camelCase 2024-08-04 15:52:15 +02:00
Zankaria
4b5e40f575 main.js: format 2024-08-04 15:50:04 +02:00
Zankaria
eb67076e60 main.js: rename dopost to camelCase 2024-08-04 15:47:38 +02:00
Zankaria
990f27e80b main.js: format getCookie 2024-08-04 15:44:12 +02:00
Zankaria
8d3bfedc72 main.js: trim 2024-08-04 15:42:02 +02:00
Lorenzo Yario
d78f865645
Merge pull request #779 from Zankaria/ban-query-truncate
Fix new_ban failing due to the message body being too big
2024-08-03 23:16:11 -07:00
Lorenzo Yario
283973c141
Merge pull request #780 from seisatsu/dev
Add a spam filter that unshortens urls (resubmission)
2024-08-03 23:15:56 -07:00
seisatsu
098edb9cd7 Add a spam filter that unshortens urls 2024-07-31 12:44:39 -05:00
Zankaria
4bc69be4bc bans.php: fix new_ban failing due to the message body being too big 2024-07-27 15:27:44 +02:00
Lorenzo Yario
a20f618d80
Create uboachan-gray.css
#777
2024-07-19 11:30:08 -07:00
Lorenzo Yario
d7468bb93b
Merge pull request #772 from vichan-devel/RealAngeleno-templateupdates
Update catalog and the index: Wildcard and excluding boards
2024-07-14 04:40:09 -07:00
Lorenzo Yario
541f31f4d1
allow excluding boards from the boardlist 2024-07-14 04:38:11 -07:00
Lorenzo Yario
c223b1c55d
allow board exclusion for the boardlist 2024-07-14 04:37:28 -07:00
Lorenzo Yario
409f571955
switch to columns of two. Make it optional for a video and other things. 2024-07-14 04:21:21 -07:00
Lorenzo Yario
d23d1526e8
forgot to remove implode() 2024-07-14 03:41:04 -07:00
Lorenzo Yario
9a80ae2434
make the wildcard the default 2024-07-14 03:38:09 -07:00
Lorenzo Yario
dba38b10d4
allow wildcard for catalog theme 2024-07-14 03:26:06 -07:00
Lorenzo Yario
89a31794d9
fixing and standardizing something i did at like 4am with tripcode disabling 2024-07-04 11:29:18 -07:00
Lorenzo Yario
1a780ce9cb
move are you sure prompt to the js file 2024-06-27 02:18:06 -07:00
Lorenzo Yario
fe8fa0da8a
move to the js file 2024-06-27 02:13:54 -07:00
Lorenzo Yario
e12cbf6d80
Merge pull request #767 from Zankaria/patch-1
docker: remove PEAR leftovers
2024-06-24 17:02:10 -07:00
Lorenzo Yario
0df33b4956
Merge pull request #768 from Zankaria/docker-patch
Improve docker composer
2024-06-24 17:01:56 -07:00
Zankaria
ef1939500c docker: use modern compose file naming scheme 2024-06-23 15:54:21 +02:00
Zankaria
555d14b7ae docker: make the compose local instance folder file parametrizable 2024-06-23 15:53:42 +02:00
Zankaria
281f391205
docker: remove PEAR leftovers 2024-06-23 13:13:45 +02:00
Lorenzo Yario
b21865853b
fix the rest of local-time.js somehow 2024-06-20 20:38:35 -07:00
Lorenzo Yario
5b0a7fb975
Merge pull request #765 from perdedora/hash-passwords
Hash poster passwords
2024-06-20 16:05:55 -07:00
fowr
e9f1d59209
posts.sql: update column password 2024-06-20 10:33:51 -03:00
Weav
fee67b6719
Merge branch 'dev' into hash-passwords 2024-06-20 13:21:05 +00:00
fowr
fff9b88c6d
hash poster passwords 2024-06-20 10:11:47 -03:00
Lorenzo Yario
8d37f1dd2c
Merge pull request #764 from Zankaria/patch-1
install.php: fix https check
2024-06-20 03:40:13 -07:00
Zankaria
991ed657fb
install.php: fix https check 2024-06-15 00:53:49 +02:00
Lorenzo Yario
ad532d1d2d
Merge pull request #762 from vichan-devel/RealAngeleno-patch-12
fix local-time somehow
2024-06-06 00:02:35 -07:00
Lorenzo Yario
d2f1b7e0e0
fix local-time somehow
this fixes it. i don't know how. don't ask. i'm not a javascript guy much.
2024-06-06 00:02:06 -07:00
Lorenzo Yario
2d6b599b26
Merge pull request #761 from vichan-devel/parsedown
Parsedown
2024-06-05 18:49:27 -07:00
Lorenzo Yario
bd7eb130ea
use current website 2024-06-05 18:08:23 -07:00
Lorenzo Yario
f852172e9b
no they're not 2024-06-05 18:05:43 -07:00
Lorenzo Yario
809ab99c9b
allow images for markdown 2024-06-05 18:02:08 -07:00
Lorenzo Yario
5c99c8395e
add parsedown 2024-06-05 18:00:24 -07:00
Lorenzo Yario
878a67389a
Merge pull request #758 from Zankaria/refactor-ban-log
Refactor ban log
2024-05-22 23:15:30 -07:00
Lorenzo Yario
d990c344d4
Merge pull request #759 from Zankaria/fake-copy
Use hardlinks instead of copying the file
2024-05-22 23:14:49 -07:00
Zankaria
88a48befd4 pages.php: use link to create hardlinks instead of full file copy for thread moving 2024-05-23 00:05:43 +02:00
Zankaria
7e4dd5567b bans.php: always print modLog 2024-05-22 22:14:38 +02:00
Zankaria
8963ebfce9 bans.php: simplify modLog string 2024-05-22 22:14:08 +02:00
Lorenzo Yario
9236e10f37
add ) 2024-05-20 04:32:30 -07:00
Lorenzo Yario
9aaed32c57
Merge pull request #752 from vichan-devel/RealAngeleno-cattychanges
remove redundant second catalog button on catalog-link.js
2024-05-18 03:26:03 -07:00
Lorenzo Yario
055d31d2db
Merge pull request #749 from vichan-devel/RealAngeleno-datetime
fix bug with datetime
2024-05-17 19:03:51 -07:00
Lorenzo Yario
de39780194
Merge pull request #753 from Zankaria/fix-install
Fix HTTPS check
2024-05-17 15:05:48 -07:00
Zankaria
37658f1817 install.php: fix HTTPS check 2024-05-17 14:13:40 +02:00
Lorenzo Yario
00be5e6ced
remove redundant second catalog button 2024-05-17 00:51:24 -07:00
Lorenzo Yario
605f198d8c
fix bug with datetime 2024-05-16 22:51:20 -07:00
Lorenzo Yario
3d797c95ca
The https check doesn't work properly if we run it inside the array. 2024-05-16 22:12:12 -07:00
Lorenzo Yario
566b04f94e
add a message for those not using https 2024-05-16 21:26:36 -07:00
Lorenzo Yario
7899476323
Merge pull request #746 from Zankaria/secure-login-triple
Rework secure_login_only configuration option to allow secure default and header checking
2024-05-16 00:55:16 -07:00
Zankaria
d700aa0522 Rework secure_login_only configuration option to allow secure default and header checking 2024-05-11 16:02:15 +02:00
Lorenzo Yario
feb2860d9e
Merge pull request #745 from Zankaria/fix-deprecations
Fix more deprecations
2024-05-11 06:57:43 -07:00
Zankaria
9f46f0fdd4 functions.php: do not fail fail_unlink if the file does not exist 2024-05-11 15:38:17 +02:00
fowr
ba2daa88e6 fix conversion of false to array 2024-05-11 15:38:17 +02:00
Lorenzo Yario
519dd27221
but we're using datetime 2024-05-11 05:03:35 -07:00
Lorenzo Yario
cc55563411
let's continue to use current date/time formatting 2024-05-11 04:58:59 -07:00
Lorenzo Yario
de91423a9f
Merge pull request #744 from vichan-devel/RealAngeleno-httpsonly
modify how https only works, disabling by default and allowing cloudflare.
2024-05-11 04:46:58 -07:00
Lorenzo Yario
f9c54dbbbe
removed redundant message 2024-05-11 04:46:08 -07:00
Lorenzo Yario
273722dc7e
set to false by default. this'll probably become true eventually though 2024-05-11 04:45:39 -07:00
Lorenzo Yario
091c0442e8
allow cloudflare and other proxies to still count as https 2024-05-11 04:42:45 -07:00
Lorenzo Yario
b2f246abb0
Merge pull request #743 from Zankaria/fix-deprecations
Fix deprecations
2024-05-11 04:38:59 -07:00
Zankaria
96bebe8c79 post.php: fix broken JS cookie setting 2024-05-11 12:44:16 +02:00
Zankaria
827373819f docker: add compose documentation notes 2024-05-11 12:34:41 +02:00
fowr
ffa5c018e7 functions.php: add missing global 2024-05-11 12:24:50 +02:00
fowr
1a59e663c6 anti-bot.php: fix implicit conversion from float 2024-05-11 12:21:59 +02:00
fowr
010ab2bf62 post.php: add default exif_stripped 2024-05-11 12:19:42 +02:00
Zankaria
faa43cb8a6 image.php: do not delete moved images 2024-05-11 12:05:10 +02:00
Zankaria
dd224cea58 functions.php: handle null body in remove_modifiers 2024-05-11 11:48:01 +02:00
Zankaria
4c731ba241 auth.php: check if cookie exists 2024-05-11 00:51:02 +02:00
Zankaria
ed05049777 functions.php: fix null parameter 2024-05-11 00:51:02 +02:00
Lorenzo Yario
49d815c2ee
Merge pull request #742 from Zankaria/config-reenable-syslog
config.php: reenable syslog default
2024-05-10 15:41:18 -07:00
Lorenzo Yario
e5dc2cd5ce
Merge pull request #741 from Zankaria/fix-login
Fix the login
2024-05-10 15:41:02 -07:00
Zankaria
44fd0dfb82 config.php: reenable syslog default 2024-05-11 00:16:18 +02:00
Zankaria
b90d6f5680 Fix broken login 2024-05-11 00:04:20 +02:00
Lorenzo Yario
8170e226ec
we don't need vichan to require two versions of php. removed redundant 5.6. 2024-05-09 23:30:07 -07:00
Lorenzo Yario
a7cb62349c
Merge pull request #739 from vichan-devel/RealAngeleno-searchexclusion
Allow board exclusion for search
2024-05-09 23:22:55 -07:00
Lorenzo Yario
21cbdfef04
change the search exclusion error to just be a blacklist via server side verification 2024-05-09 23:19:50 -07:00
Lorenzo Yario
ad653af082
allow excluding searches from boards 2024-05-09 23:06:45 -07:00
Lorenzo Yario
2fa3b3c93e
allow exclusion of boards 2024-05-09 23:00:51 -07:00
Lorenzo Yario
021e20f373
Merge pull request #714 from Zankaria/fix-string-interning
Fix: substitute deprecated string interning syntax
2024-05-09 22:48:10 -07:00
Lorenzo Yario
34a3dcac24
Merge pull request #713 from Zankaria/update-template-datetime
Update template datetime
2024-05-09 22:47:52 -07:00
Lorenzo Yario
b1bdb1222a
Add files via upload 2024-05-08 18:53:29 -07:00
Lorenzo Yario
b5182a1864
Merge pull request #738 from vichan-devel/disabletripcodes
Disabletripcodes
2024-05-08 18:48:09 -07:00
Lorenzo Yario
82881fe512
disabling tripcodes 2024-05-08 18:34:35 -07:00
Lorenzo Yario
b0e6580845
Merge pull request #736 from papereth/patch-1
Fix Exif leak in JPEG orientation conversion code
2024-05-08 17:44:48 -07:00
papereth
0dd064b2ea
Fix Exif leak in JPEG orientation conversion code
https://github.com/vichan-devel/vichan/issues/735
2024-05-04 15:01:17 +01:00
Lorenzo Yario
a7658fe3c2
allow tripcodes to be disabled 2024-05-03 15:54:09 -07:00
Lorenzo Yario
ae72ed42ad
Merge pull request #733 from Zankaria/improve-auth
Improve authentication security
2024-05-03 14:00:59 -07:00
Lorenzo Yario
12bcc63753
Merge branch 'dev' into improve-auth 2024-05-03 14:00:50 -07:00
Lorenzo Yario
67fbd90f0d
Merge pull request #734 from Zankaria/refactor-functions2
(Partial) refactor of functions.php
2024-05-03 13:57:16 -07:00
Zankaria
1b6d6f38f1 auth.php: add typing 2024-04-30 19:47:31 +02:00
Zankaria
da4842eb7b auth.php: disallow unencrypted logins by default 2024-04-30 19:45:15 +02:00
Zankaria
0c51d46cdf auth.php: check if the cookie is set before deletion 2024-04-30 19:45:15 +02:00
Zankaria
9db8444c3c auth.php: use secured names and directives for mod cookies 2024-04-30 19:44:11 +02:00
Zankaria
abdf82e1c8 auth.php: remove obsolete code 2024-04-30 19:44:11 +02:00
Zankaria
5a378dd605 config.php: reduce default login cookie expire timeout 2024-04-30 19:42:01 +02:00
Zankaria
5bb1202def Add num.php to autoloader 2024-04-30 15:57:02 +02:00
Zankaria
f6960b8b3a functions.php: format and trim 2024-04-30 15:57:02 +02:00
Zankaria
7041cd13df functions: split off numeric functions 2024-04-30 15:56:59 +02:00
Zankaria
687e8e078a Add format.php to autoload 2024-04-30 15:56:56 +02:00
Zankaria
b7eed34b83 functions: split off time formatting functions 2024-04-30 15:56:53 +02:00
Zankaria
39ce0e7dfc auth.php: trim 2024-04-30 11:36:11 +02:00
Lorenzo Yario
6cd11d546f
undid to do a pr for it 2024-04-29 15:20:17 -07:00
Lorenzo Yario
4674f44327
soyjak upstream for api changes 2024-04-29 15:18:54 -07:00
Lorenzo Yario
4cfb1ec576
Merge pull request #729 from Zankaria/improve-social-media-cards
Improve social media cards
2024-04-28 13:34:53 -07:00
Lorenzo Yario
1df9d2d84f
Merge pull request #730 from Zankaria/move-twig-cache
Move twig template cache
2024-04-28 13:34:24 -07:00
Lorenzo Yario
51aa6e3813
Merge pull request #731 from Zankaria/improve-mobile-user-options
Limit user options panel width on mobile
2024-04-28 13:34:14 -07:00
Zankaria
af06d84094 style.css: limit user options panel width on mobile 2024-04-27 22:21:20 +02:00
Zankaria
ebbb5fce53 Move twig template cache 2024-04-26 14:03:57 +02:00
discomrade
735180cf54 Improve social media cards 2024-04-24 17:22:39 +02:00
Zankaria
4bb0f40cd1 index.html: trim 2024-04-24 17:01:38 +02:00
Lorenzo Yario
7025035376
Merge pull request #728 from vichan-devel/RealAngeleno-patch-5
bugfix for ban appeals page
2024-04-19 12:04:09 -07:00
Lorenzo Yario
85471e007e
vichan likes to error on the ban appeals page if this isn't set this way 2024-04-19 12:03:49 -07:00
Lorenzo Yario
19fa804116
Merge pull request #721 from Zankaria/dockerize
Dockerize Vichan
2024-04-19 01:04:16 -07:00
Zankaria
2836ace551 readme: add basic docker documentation in the README 2024-04-18 23:44:09 +02:00
Zankaria
9d7ddd46c5 dokcer: cache webp images files in nginx 2024-04-18 23:33:47 +02:00
Zankaria
cbb1571063 docker: remove duplicated nginx configuration 2024-04-18 23:32:48 +02:00
Lorenzo Yario
0278ce16be
Merge pull request #720 from Zankaria/fix-installation
Better error SQL reporting on installation
2024-04-18 14:11:10 -07:00
Lorenzo Yario
004481b920
Merge pull request #723 from Zankaria/improve-context-init
Improve Context initialization
2024-04-18 14:10:59 -07:00
Lorenzo Yario
73a83e5dc9
Merge pull request #725 from Zankaria/banners-redirect
Make banner access redirect instead of serving the image directly
2024-04-18 14:10:48 -07:00
Lorenzo Yario
a19e4cc755
Merge pull request #726 from Zankaria/post-filter-by-flag
Filter posts by flag
2024-04-18 14:10:23 -07:00
Lorenzo Yario
3175f3627d
Merge pull request #724 from Zankaria/fix-hcaptcha
Fix HCaptcha
2024-04-18 14:09:55 -07:00
discomrade
df07515397 Enable filtering by flag name 2024-04-17 10:16:27 +02:00
Zankaria
0428c35684 b.php: make banners redirect instead of serving the image directly 2024-04-17 10:15:55 +02:00
Zankaria
b86b9e375d post.php: fix hcaptcha reading wrong post field 2024-04-16 22:39:32 +02:00
Zankaria
c3619c49fb docker: prepare compose for multiple test instances 2024-04-16 22:32:41 +02:00
Zankaria
024f955338 docker: remove special handling of instance-config.php from build 2024-04-16 22:32:41 +02:00
Zankaria
bf4f388a04 docker: make non-profile the default compose setting 2024-04-16 22:32:41 +02:00
Zankaria
f161de3d57 docker: format compose file 2024-04-16 22:32:41 +02:00
Zankaria
107592f70c docker: simplify composer file 2024-04-16 22:32:41 +02:00
Zankaria
fbbdb5afd6 docker: fix variable checking in bootstrapping script 2024-04-16 22:32:41 +02:00
Zankaria
5c99b0f4f3 docker: enable profiling with xdebug 2024-04-16 22:32:41 +02:00
Zankaria
fb191a0ffd docker: change compose database root password 2024-04-16 22:32:41 +02:00
Zankaria
575b265c74 docker: adjust php-fpm pool log config on compose 2024-04-16 22:32:41 +02:00
Zankaria
050bc59588 docker: enable JIT by default on compose 2024-04-16 22:32:41 +02:00
Zankaria
f8ea32376e docker: remove leftchan references from compose 2024-04-16 22:32:41 +02:00
Zankaria
5a5d315330 docker: remove leftypol branding from nginx compose 2024-04-16 22:32:41 +02:00
Zankaria
729219a3c4 docker: bootstrap remove leftypol specific files 2024-04-16 22:32:41 +02:00
Zankaria
d117619ce6 docker: boostrap script handle secrets.php, copy static files 2024-04-16 22:32:41 +02:00
Zankaria
5bdbe49f38 docker: move image to alpine linux 2024-04-16 22:32:41 +02:00
Zankaria
711e824153 docker: remove lainchan branding from compose file 2024-04-16 22:32:41 +02:00
Zankaria
9d9804db13 docker: compose mount local-www as root directory in nginx 2024-04-16 22:32:41 +02:00
Zankaria
79183ae8e6 docker: handle secrets.php 2024-04-16 22:32:41 +02:00
Zankaria
eb01768191 docker: use less used port for compose 2024-04-16 22:32:41 +02:00
Zankaria
c058ec12f9 Remove template/cache directory 2024-04-16 22:32:41 +02:00
Zankaria
1fed05c5ee docker: ignore empty gitkeep directories 2024-04-16 22:32:41 +02:00
Zankaria
2af07d006b docker: create empty robots.txt 2024-04-16 22:32:41 +02:00
Zankaria
8799c142b0 install.php: check that secrets.php is writable 2024-04-16 22:32:41 +02:00
Zankaria
3de9fa24dd template.php install.php: handle cache directory being a symlink 2024-04-16 22:32:41 +02:00
Zankaria
efdf93e3dd template.php: trim 2024-04-16 22:32:41 +02:00
Zankaria
7aca69125f docker: extract the vichan directory and make it optionally exposable 2024-04-16 22:32:41 +02:00
Zankaria
b1b28dcb90 docker-compose: use local www root 2024-04-16 22:32:41 +02:00
Zankaria
bd3bf7e4f8 docker: reduce file permissions 2024-04-16 22:32:41 +02:00
Zankaria
7979404c1b docker: change user to www-data 2024-04-16 22:32:41 +02:00
Zankaria
d55961995c docker: change the work directory to /var/www 2024-04-16 22:32:41 +02:00
Zankaria
482962844a docker: fix missing tmp directory 2024-04-16 22:32:41 +02:00
Zankaria
cc8e458906 docker: split up application and dependency layers 2024-04-16 22:32:41 +02:00
Zankaria
1d385ad6aa docker: remove "meaningless" bits from nginx configuration 2024-04-16 22:32:41 +02:00
Zankaria
62f0e9894c docker: trim PHP configuration 2024-04-16 22:32:41 +02:00
zeke
7ac0460b0a Apply suggested changes 2024-04-16 22:32:41 +02:00
zeke
460aee0dad Remove unused Dockerfile 2024-04-16 22:32:41 +02:00
zeke
03228eb87d Fix user and group creation for docker containers 2024-04-16 22:32:41 +02:00
zeke
f3c7bad9cd Remove extension lines (added by docker-php-ext-enable) 2024-04-16 22:32:41 +02:00
zeke
fc63de4ed4 Use two Dockerfiles, move Docker stuff to /docker 2024-04-16 22:32:41 +02:00
zeke
5ca2d194b4 Update dependencies for Docker image 2024-04-16 22:32:41 +02:00
Zankaria
90235b2bab docker: remove unused configuration 2024-04-16 22:32:41 +02:00
Barbara Pitt
3a769b437f adding docker items 2024-04-16 22:32:41 +02:00
Zankaria
8389c399bd Context: shorter lazy initialization 2024-04-16 22:30:37 +02:00
Lorenzo Yario
73f2e3222b
Merge pull request #722 from Zankaria/dep-inj-factory
Splits the dependecy container from the dependency building
2024-04-09 05:37:21 -05:00
Zankaria
a83bcf14a4 Context: simplify lazy initialization 2024-04-09 11:43:46 +02:00
Zankaria
f93dd1fae5 Context: extract dependency building from the container 2024-04-09 11:33:06 +02:00
Zankaria
fc716fd0a8 install.php: better SQL error reporting 2024-04-07 19:59:08 +02:00
Lorenzo Yario
3c49645af0
Merge pull request #717 from Zankaria/dep-inj-logging
Add logger by dependency injection
2024-04-04 19:43:46 -07:00
Lorenzo Yario
1109ef3ba6
Merge pull request #718 from Zankaria/fix-deprecation
Fix deprecations in post.php
2024-04-04 19:43:33 -07:00
Zankaria
710f6aa6c2 post.php: use logger 2024-04-04 12:44:37 +02:00
Zankaria
55cb6bc400 context.php: add log driver 2024-04-04 12:44:37 +02:00
Zankaria
f05c290b67 log-driver.php: autoload the logging dirver 2024-04-04 12:44:37 +02:00
Zankaria
28395d55e5 Refactor the logging system 2024-04-04 12:44:37 +02:00
Zankaria
4d9d68b550 Substitute deprecated php functions calls 2024-04-04 11:09:43 +02:00
Lorenzo Yario
5680d73f08
Merge pull request #716 from Zankaria/adjust-image-stripping
Enhance image metadata ops
2024-04-03 14:23:39 -07:00
Zankaria
eaacf27199 post.php: do not strip orientation metadata 2024-04-03 21:38:16 +02:00
Zankaria
6ceee8261e post.php: strip and reorient png and webp images 2024-04-03 21:34:51 +02:00
Zankaria
2bb1b0b9d4 post.php: remove double check 2024-04-03 21:24:10 +02:00
Zankaria
9072ce5992 post.php: strip metadata from png and webp image file types 2024-04-03 21:23:48 +02:00
Lorenzo Yario
98650ec2e7
Merge pull request #677 from Zankaria/refactor-queue
Refactor queue
2024-04-03 12:17:50 -07:00
Lorenzo Yario
99d55ca2b5
Merge pull request #711 from Zankaria/add-dep-injection
Fixed share REST call code and separate components via dependency injection
2024-04-03 12:17:33 -07:00
Lorenzo Yario
59b763fd53
Merge pull request #715 from vichan-devel/revert-668-remove-check-updates
leno merges another commit while half asleep
2024-04-03 12:16:56 -07:00
Lorenzo Yario
429ae8e352
Revert "Remove check-updates functionality" 2024-04-03 12:15:06 -07:00
Lorenzo Yario
e811a9deeb
Merge pull request #668 from Zankaria/remove-check-updates
Remove check-updates functionality
2024-04-03 12:14:51 -07:00
Zankaria
c91c58ed07 Fix: substitute deprecated string interning syntax 2024-04-03 19:18:41 +02:00
Zankaria
99133c90fa config.php: fix date time diplay documentation 2024-04-03 17:38:12 +02:00
Zankaria
4ffe91e384 templates: substitute deprecated functions 2024-04-03 17:33:53 +02:00
Zankaria
1fa60e7386 index.hmtl: trim template 2024-04-03 17:33:53 +02:00
Zankaria
7479360aad catalog.html: format template 2024-04-03 17:33:48 +02:00
Zankaria
9a014e8557 template.php: fix deprecated string interning syntax 2024-04-03 17:33:48 +02:00
Zankaria
542c9f3342 Remove check-updates functionality.
It relies on the defunct vichan.net website, no point keeping it around.
2024-04-03 14:38:26 +02:00
Zankaria
f47332cdff Allow queue push to fail gracefully 2024-04-03 14:34:43 +02:00
Zankaria
09dc44ec40 functions.php: trim 2024-04-03 14:34:42 +02:00
Zankaria
e61ed35aa0 Refactor queue.php 2024-04-03 14:33:51 +02:00
Zankaria
55034762b0 Format queue.php 2024-04-03 14:33:51 +02:00
Zankaria
760431606d Refactor lock.php 2024-04-03 14:33:51 +02:00
Zankaria
00b05099f3 Format lock.php 2024-04-03 14:33:51 +02:00
Zankaria
8120c42440 Format injected javascript on failed native captcha 2024-04-03 14:33:38 +02:00
Zankaria
650ef8bcc2 Fix crash if no captcha is enabled 2024-04-03 14:33:38 +02:00
Zankaria
3016d69428 Share REST call code and separate components via dependency injection 2024-04-03 14:33:38 +02:00
Lorenzo Yario
c3de90075e
Merge pull request #712 from Zankaria/fix-bad-report
Handle reporting non-existing posts.
2024-04-02 03:41:21 -07:00
Zankaria
03a875f663 Handle reporting non-existing posts. 2024-04-01 19:55:32 +02:00
Lorenzo Yario
74c2aec338
Merge pull request #708 from vichan-devel/revert-707-revert-704-revert-688-add-dep-injection
reverting one last time because of errors in my test env
2024-03-30 22:47:55 -07:00
Lorenzo Yario
95153233eb
Revert "Revert "Revert "Share REST call code and separate components via dependency injection""" 2024-03-30 22:46:35 -07:00
Lorenzo Yario
be3437e452
Merge pull request #707 from vichan-devel/revert-704-revert-688-add-dep-injection
Revert "Revert "Share REST call code and separate components via dependency injection""
2024-03-30 22:34:42 -07:00
Lorenzo Yario
67475c2c2f
Revert "Revert "Share REST call code and separate components via dependency injection"" 2024-03-30 22:34:30 -07:00
Lorenzo Yario
4094437464
Merge pull request #706 from vichan-devel/revert-705-revert-666-fix-composer
Revert "Revert "Fix composer.json platform""
2024-03-30 22:33:44 -07:00
Lorenzo Yario
d0c0d272af
Revert "Revert "Fix composer.json platform"" 2024-03-30 22:32:45 -07:00
Lorenzo Yario
2fa28510b9
Merge pull request #705 from vichan-devel/revert-666-fix-composer
Revert "Fix composer.json platform"
2024-03-30 22:31:35 -07:00
Lorenzo Yario
24708dec7e
Revert "Fix composer.json platform" 2024-03-30 22:31:04 -07:00
Lorenzo Yario
06ea4898d4
Merge pull request #704 from vichan-devel/revert-688-add-dep-injection
Revert "Share REST call code and separate components via dependency injection"
2024-03-30 22:25:25 -07:00
Lorenzo Yario
f5328a436c
Revert "Share REST call code and separate components via dependency injection" 2024-03-30 22:24:20 -07:00
Lorenzo Yario
3d2f0b6a1b
Merge pull request #688 from Zankaria/add-dep-injection
Share REST call code and separate components via dependency injection
2024-03-30 22:15:44 -07:00
Lorenzo Yario
45f476084e
Merge pull request #693 from Zankaria/premade-ban-reasons
Add premade ban reasons
2024-03-30 22:15:20 -07:00
Lorenzo Yario
38b47a0844
Merge pull request #698 from Zankaria/calc-file-size-after-strip
Calculate the file size after stripping the metadata off an image.
2024-03-30 22:15:10 -07:00
Lorenzo Yario
afe7c73195
Merge pull request #699 from Zankaria/remove-no-op
Remove no-op lines from post.php
2024-03-30 22:14:58 -07:00
Lorenzo Yario
55984b4260
Merge pull request #700 from Zankaria/optimize-ban-queries
Optimize Bans queries
2024-03-30 22:14:47 -07:00
Lorenzo Yario
b10ca57da1
Merge pull request #666 from Zankaria/fix-composer
Fix composer.json platform
2024-03-30 21:21:30 -07:00
Lorenzo Yario
c5ca05185f
Merge pull request #702 from Zankaria/show-ban-id2
Show ban id on ban page.
2024-03-27 18:10:52 -07:00
Zankaria
d4bcc34d6d Add ban id to ban page. 2024-03-26 15:29:20 +01:00
Zankaria
b739a8e846 banned.html: trim 2024-03-26 15:26:55 +01:00
Zankaria
018da09ac5 Fix CaptchaQueries naming 2024-03-26 14:16:19 +01:00
Zankaria
3e3fa057d5 bans.php: rebuild themes only if bans are deleted 2024-03-22 10:59:22 +01:00
Zankaria
67b88ec78f bans.php: group deletions 2024-03-22 10:59:13 +01:00
Zankaria
a2eb3d9053 bans.php: trim 2024-03-22 10:57:10 +01:00
Zankaria
27ddd5158d psot.php: remove no-op lines 2024-03-21 16:15:49 +01:00
Zankaria
e455080d42 post.php: refactor image metadata stripping into function 2024-03-21 16:02:09 +01:00
discomrade
0cefa9353b Recalculate filesize after stripping metadata 2024-03-21 15:42:48 +01:00
Zankaria
af8240e166 Autoload CaptchaQueries 2024-03-21 15:14:13 +01:00
Zankaria
dc903017ca Add CaptchaQueries 2024-03-21 15:14:13 +01:00
Zankaria
819ce71c55 Autload HttpDriver 2024-03-21 15:14:13 +01:00
Zankaria
2cad97775a post.php: use HttpDriver for remote file download 2024-03-21 15:14:13 +01:00
Zankaria
c20b0ba6f0 Add context dependency container 2024-03-21 15:14:13 +01:00
Zankaria
3dc239e204 http-driver: refactor 2024-03-21 15:14:13 +01:00
Zankaria
65cebe9bd5 http-driver: add file size limit and timeout support 2024-03-21 15:14:13 +01:00
Zankaria
2a228e8ee4 Add http curl driver 2024-03-21 15:14:13 +01:00
Lorenzo Yario
0c3159673d
Merge pull request #692 from Zankaria/simple-antispam
Prettier simple-antispam documentation
2024-03-16 15:39:57 -07:00
Lorenzo Yario
70410e5e61
Merge pull request #695 from Zankaria/post-delete-ip-modlog
Report in the modlog the IP that deleted their own post
2024-03-15 13:23:08 -07:00
Lorenzo Yario
32d3573e56
kept since it sounds better 2024-03-15 13:22:45 -07:00
Lorenzo Yario
3c23e01dab
Merge pull request #696 from Zankaria/ban-appeals-limits
Add maximum length of ban appeal
2024-03-15 09:48:25 -07:00
Lorenzo Yario
44684496c7
Merge pull request #697 from Zankaria/report-limits
Limit the report length
2024-03-15 09:47:06 -07:00
Zankaria
2a8b69fa77 Add maximum report length 2024-03-15 16:37:59 +01:00
vholmes
61cdca7207 Prevents reports with too many characters 2024-03-15 16:34:05 +01:00
Zankaria
d5109426d9 Prettier simple-antispam 2024-03-15 16:08:45 +01:00
discomrade
e80549a881 Enforce maximum length of ban appeal 2024-03-15 16:02:35 +01:00
Zankaria
caa05e41a2 Add IPs of users deleting their own post to the mod log 2024-03-15 12:02:33 +01:00
discomrade
43973862dd Added Feature - Premade Ban Reasons
see 13ac9172e7
2024-03-14 15:55:49 +01:00
Lorenzo Yario
3ac86a074a
Merge pull request #687 from Zankaria/trim-functions
Trim the whitespace in functions.php
2024-03-14 06:12:42 -07:00
Lorenzo Yario
9841102494
Merge pull request #691 from vichan-devel/simplespamfix
Simplespamfix
2024-03-14 06:11:58 -07:00
Lorenzo Yario
f48cf068d6
make case-insensitive 2024-03-14 06:10:18 -07:00
Lorenzo Yario
954bb08762
disable by default, like other captchas 2024-03-14 06:06:28 -07:00
Lorenzo Yario
28df28de26
add some more info about this as this is basically questycaptcha 2024-03-14 06:05:43 -07:00
Lorenzo Yario
33534b5856
fix critical typo for simple spam 2024-03-14 05:58:23 -07:00
Lorenzo Yario
e3ae4aee80
Merge pull request #689 from Zankaria/faster-delete
Speed up page builds on delete
2024-03-14 05:22:34 -07:00
Lorenzo Yario
032a6f42e3
Merge pull request #690 from Zankaria/simple-antispam
Add simple antispam
2024-03-14 05:22:22 -07:00
Zankaria
e2d771239c Critically enhance the simple antispam mechanism 2024-03-14 12:50:19 +01:00
Your Name
6dabfa08bc Simple anti-spam mechanism 2024-03-14 12:50:19 +01:00
nonmakina
fff3e11c48 use more cache. Speeds up page builds (#72)
use more cache. Speeds up page builds.
Tested as much as reasonably possible. Works well.
cuts self delete from ~8 seconds to ~1 second. and mod delete from 10-14 seconds to ~4 seconds.
Co-authored-by: nonmakina <nonmakina@leftypol.org>
Co-committed-by: nonmakina <nonmakina@leftypol.org>
2024-03-14 12:28:02 +01:00
Zankaria
b25cffe12e functions.php: trim 2024-03-14 10:01:13 +01:00
Lorenzo Yario
0296301fff
use the current domain 2024-03-11 18:54:20 -07:00
Lorenzo Yario
e855d5213b
Update README.md 2024-03-11 16:17:02 -07:00
Lorenzo Yario
ab06e62266
Merge pull request #684 from Zankaria/fix-bad-download-parameter
post.php: fix bad call to download_file_into with wrong argument
2024-03-11 16:13:37 -07:00
Lorenzo Yario
9aba8f35b6
Merge pull request #686 from Zankaria/refactor-post-ocr
post.php: refactor image OCR into function
2024-03-11 16:13:26 -07:00
Lorenzo Yario
4e707ab9ae
Merge pull request #685 from Zankaria/remove-cache-backends
Remove cache backends
2024-03-11 15:58:35 -07:00
Zankaria
2f88d0809f Remove APC support 2024-03-11 10:24:35 +01:00
Zankaria
0154e54f85 Remove xcache support 2024-03-11 10:24:35 +01:00
Zankaria
8cebc7f80c mod.php: trim 2024-03-11 10:24:35 +01:00
Zankaria
575cb856a5 install.php: trim 2024-03-11 10:24:35 +01:00
Zankaria
6715991cdd README: trim 2024-03-11 10:24:35 +01:00
Zankaria
58134f8cde cache.php: trim 2024-03-11 10:24:35 +01:00
Zankaria
f683c72c39 config.php: trim 2024-03-11 10:24:30 +01:00
Lorenzo Yario
557b183d36
Merge pull request #675 from Zankaria/remove-manual-orient-2
Remove 'convert_manual_orient' functionality.
2024-03-11 00:00:58 -07:00
Zankaria
9ae988dd6f post.php: refactor image OCR into function 2024-03-08 10:24:02 +01:00
Zankaria
8978bb5442 post.php: fix bad call to download_file_into with wrong argument 2024-03-07 12:37:17 +01:00
Lorenzo Yario
4439f1736a
Merge pull request #673 from Zankaria/remove-remote
Remove remote server support
2024-03-05 15:04:08 -08:00
Lorenzo Yario
59c9e1771a
Merge pull request #682 from Zankaria/appeal-count
Show ban appeal count in bold on mod dashboard
2024-02-26 19:41:40 -08:00
discomrade
1ed75a58c2 Show ban appeal count on mod dashboard 2024-02-23 22:59:32 +01:00
Zankaria
f7a8cb258f dashboard template: trim 2024-02-23 22:59:32 +01:00
Zankaria
f317691dcd mod pages: trim 2024-02-23 22:59:32 +01:00
Lorenzo Yario
350060e7a6
Merge pull request #681 from vichan-devel/innodb
Innodb
2024-02-23 10:31:46 -08:00
Lorenzo Yario
7e19026be0
we don't need myisam 2024-02-23 10:31:25 -08:00
Lorenzo Yario
1b539ae40e
innodb 2024-02-23 09:19:54 -08:00
Lorenzo Yario
3f529db5e4
wrong branch. oops. 2024-02-23 09:19:23 -08:00
Lorenzo Yario
0c6f7c8237
innodb 2024-02-23 09:18:50 -08:00
Lorenzo Yario
492da02b53
change to innodb 2024-02-23 09:17:25 -08:00
Lorenzo Yario
3d05ba0247
Merge pull request #678 from Zankaria/format-filter
Format filter
2024-02-23 09:15:13 -08:00
Lorenzo Yario
543d5e1757
make it harder to accidentally unban everyone 2024-02-22 18:40:37 -08:00
Lorenzo Yario
4bda535c66
Merge pull request #679 from Zankaria/remove-captcha-sql
Remove obsolete dbschema.sql
2024-02-20 01:26:00 -08:00
Zankaria
cb7a6ecf45 Remove obsolete dbschema.sql 2024-02-19 15:48:56 +01:00
Zankaria
db7d51670e Format filter 2024-02-16 16:01:01 +01:00
Zankaria
24ebabb976 Remove 'convert_manual_orient' functionality.
It was supposed to help in case the user had an unspecified imagemagik version that was old in 2013...
2024-02-14 23:34:08 +01:00
Zankaria
dd5c25f99c Remove remote server support
The functionality was marked as "I'm not even sure if this code works anymore" 11 years ago...
2024-02-14 23:00:52 +01:00
Lorenzo Yario
e52c996a56
Merge pull request #669 from Zankaria/remove-ban-php
Remove ban.php
2024-02-14 03:44:38 -08:00
Lorenzo Yario
421e7ff283
Merge pull request #671 from vichan-devel/webpsupport
add webp support to vichan

exact changes are on soyjak.party and work
2024-02-14 03:19:19 -08:00
Lorenzo Yario
2a0c495b59
webp support 2024-02-14 03:15:21 -08:00
Lorenzo Yario
acc284004f
Merge pull request #670 from Zankaria/remove-polyfill
Remove polyfills for php 5.4 and 5.6
2024-02-14 03:13:55 -08:00
Lorenzo Yario
23670bae4f
webp support by default 2024-02-14 03:12:59 -08:00
Zankaria
6cf8c393b5 Remove polyfills for php 5.4 and 5.6 2024-02-14 11:24:40 +01:00
Zankaria
fde425111c Remove bans.php 2024-02-14 11:12:42 +01:00
Lorenzo Yario
77bec421d9
webp 2024-02-14 01:18:45 -08:00
Lorenzo Yario
0e2795d355
Merge pull request #665 from Zankaria/remove-bmp
Remove the custom BMP polyfill.
2024-02-12 18:47:12 -08:00
Zankaria
b35990e1cd Fix composer.json platform 2024-02-09 14:49:12 +01:00
Zankaria
fb3843efd5 Remove the custom BMP polyfill.
It was previously required to support PHP < 7.2, but now the minimum supported version is PHP 7.4
2024-02-07 23:24:34 +01:00
Lorenzo Yario
5867963747
Merge pull request #662 from vichan-devel/revert-661-refactor-functions
Revert "Initial break up of functions.php"
2024-02-04 05:53:52 -08:00
Lorenzo Yario
ec515621eb
Revert "Initial break up of functions.php" 2024-02-04 05:53:06 -08:00
Lorenzo Yario
4bd3fdb8a9
Merge pull request #658 from Zankaria/post-initial-refactor
Initial post refactor
2024-02-04 05:09:03 -08:00
Lorenzo Yario
1b33080214
Merge pull request #661 from Zankaria/refactor-functions
Initial break up of functions.php
2024-02-04 05:08:37 -08:00
Zankaria
3baa68c7b6 Initial refactor of functions.php 2024-02-03 17:17:14 +01:00
Zankaria
d3cd289511 Refactor post.php: break up file upload 2024-01-30 14:37:08 +01:00
Zankaria
c43229af8e Refactor post.php: extract symbol post body stripping 2024-01-30 14:36:31 +01:00
Zankaria
d02c4eb31d Refactor post.php: split upload file hashing to a function 2024-01-30 10:35:11 +01:00
Zankaria
15cce3a31f Fix leading whitespace in post.php 2024-01-30 10:35:07 +01:00
Lorenzo Yario
f45bc768fe
get duckroll'd 2024-01-23 14:18:20 -08:00
Lorenzo Yario
2ab6a3919b
It's 2024 2024-01-14 05:25:45 -08:00
Lorenzo Yario
8dec1f4798
Merge pull request #650 from x9a/master
Update flags
2023-12-10 14:12:48 -08:00
x9a
6af53795f5 Update flags
Update flags with their newer variants
2023-12-10 19:55:10 +03:00
RealAngeleno
e80cc95858
Merge pull request #645 from vichan-devel/RealAngeleno-patch-13
Allow prohibition of deleting old posts
2023-10-31 22:05:06 -07:00
RealAngeleno
d057c6d660
logic for preventing deletion of old posts 2023-10-31 22:03:09 -07:00
RealAngeleno
fe9573a385
allow disabling post deletion for old posts 2023-10-31 21:59:12 -07:00
RealAngeleno
f3c6093bf6
Merge pull request #643 from vichan-devel/RealAngeleno-installqol
Make templates/cache and secrets.php exist by default.
2023-10-21 23:24:55 -07:00
RealAngeleno
fa6e240c1c
QOL for mass vichan installation 2023-10-21 23:02:20 -07:00
RealAngeleno
bc05223362
Make secrets.php already exist as a QOL. 2023-10-21 22:59:45 -07:00
RealAngeleno
4545d33b74
added missing change from commit for hcaptcha 2023-10-10 13:45:23 -07:00
RealAngeleno
e9ed9acd30
fixed oversight. oops. 2023-10-04 22:50:06 -07:00
RealAngeleno
c9b05e5bfc
Merge pull request #609 from vichan-devel/discontinuation
After deliberation and discussions with perdedora and others, this can be merged.
2023-10-04 22:36:14 -07:00
RealAngeleno
2ade0b0c8a
Update composer.json 2023-10-04 21:33:37 -07:00
RealAngeleno
e5d6960e4a
Merge pull request #629 from vichan-devel/hcaptcha
Add hCaptcha support
2023-09-16 10:35:59 -07:00
RealAngeleno
5e26d5f09e
add hcaptcha support 2023-09-16 01:32:01 -07:00
RealAngeleno
f396204e44
add hcaptcha support 2023-09-16 01:31:02 -07:00
RealAngeleno
ad3731ec67
add hCaptcha support 2023-09-16 01:27:20 -07:00
RealAngeleno
cca659bd1f
Merge pull request #625 from frozenpandaman/patch-1
fix float division deprecation warning breaking `captcha.php` json
2023-09-10 21:46:19 -07:00
RealAngeleno
9c34ee778a
Merge pull request #626 from vichan-devel/RealAngeleno-patch-11
very small QOL change for ban appeals
2023-09-10 10:55:24 -07:00
RealAngeleno
eda383cbb3
very small QOL change for ban appeals 2023-09-10 10:54:49 -07:00
eli
c3c7bc4fc3
fix float division deprecation warning breaking captcha.php json 2023-09-07 05:45:14 -10:00
RealAngeleno
fbc2464c96
Merge pull request #622 from vichan-devel/RealAngeleno-patch-5
Drop-in replacement for rc4-40 encryption with aes-256-ctr

When I think about it, the above can be done later.
2023-09-05 21:33:24 -07:00
RealAngeleno
1b14830dfd
drop-in replacement for rc4-40 2023-09-01 22:16:05 -07:00
RealAngeleno
2094155b6c
Merge pull request #618 from vichan-devel/RealAngeleno-hourlylimit
Add hourly thread limit
2023-08-13 23:15:49 -07:00
RealAngeleno
997babeee0
add hourly thread limit (from npfchan) 2023-08-13 23:14:41 -07:00
RealAngeleno
503e4e39d0
hourly thread limit. Mostly from NPFchan 2023-08-13 23:13:29 -07:00
RealAngeleno
42a473ae8b
maintainers changed 2023-08-06 08:59:23 -07:00
RealAngeleno
063275c4c8
honestly the latest development version is less buggy than "vichan stable" 2023-08-05 18:28:15 -07:00
RealAngeleno
237c5c4d4b
Merge pull request #615 from vichan-devel/stickyfix
Allow image for cyclical posts to be set independently // Add mod.php logic to catalog links
2023-08-05 15:43:45 -07:00
RealAngeleno
dd5d8830d7
Add image for cyclical posts
From Wikimedia (Public domain)
2023-08-05 15:41:24 -07:00
RealAngeleno
b8190dfd06
allow cyclical images to be set independently of stickies 2023-08-05 15:38:31 -07:00
RealAngeleno
4d3ca11b91
allow cyclical images to be set independently of stickies 2023-08-05 15:35:28 -07:00
RealAngeleno
ea08c250fa
Add mod.php logic 2023-08-05 15:32:46 -07:00
RealAngeleno
4a151acb18
allow cyclical images to be set separately from stickies 2023-08-05 15:11:21 -07:00
RealAngeleno
285bb035da
Merge pull request #612 from vichan-devel/RealAngeleno-patch-9
Remove ENT_QUOTES?
2023-08-04 20:51:30 -07:00
RealAngeleno
29e02b705a
Merge pull request #613 from vichan-devel/RealAngeleno-patch-11
prohibit file-selector.js from running on ios
2023-08-03 22:33:53 -07:00
RealAngeleno
b79731c548
prohibit script from running on ios 2023-08-03 22:32:42 -07:00
RealAngeleno
fb8f1d04d0
Update functions.php 2023-08-02 18:04:49 -07:00
RealAngeleno
bee2d07499
Merge pull request #610 from vichan-devel/RealAngeleno-reportfix
Fix multi-report bug #567
2023-07-28 14:33:30 -04:00
RealAngeleno
aa0f6607cf
Fix multi-report bug #567 2023-07-28 14:32:42 -04:00
RealAngeleno
14ae2d7d06
discontinue php versions before 7.4 2023-07-26 20:59:37 -05:00
RealAngeleno
3413e74f24
discontinue older versions of php 2023-07-26 19:37:57 -05:00
RealAngeleno
9f7205a27e
drop support for anything lower than 7.4. 2023-07-26 19:36:33 -05:00
RealAngeleno
3b659732d6
no irc channel currently 2023-07-20 21:52:34 -05:00
RealAngeleno
b22b56d58f
Update README.md 2023-07-20 19:45:36 -05:00
RealAngeleno
a0da06b46b
Update README.md 2023-07-20 19:45:18 -05:00
RealAngeleno
dfbf5df0a3
current standings 2023-07-20 19:44:36 -05:00
RealAngeleno
2ef0d2796c
Merge pull request #601 from vichan-devel/revert-600-revert-597-remove_telegram
Re-apply Remove telegrams
2023-07-18 02:36:34 -07:00
RealAngeleno
70b5c80cea
fix bug with removal of telegrams 2023-07-18 02:35:56 -07:00
RealAngeleno
1a5b3c8480
Revert "Temporarily Revert "Remove telegrams" due to critical bug with posting" 2023-07-15 23:10:39 -07:00
RealAngeleno
ab2d29c8d1
Merge pull request #600 from vichan-devel/revert-597-remove_telegram
Temporarily Revert "Remove telegrams" due to critical bug with posting
2023-07-15 23:09:12 -07:00
RealAngeleno
af6bb09031
Revert "Remove telegrams" 2023-07-15 23:03:13 -07:00
RealAngeleno
7feb101bbf
Merge pull request #597 from perdedora/remove_telegram
Telegrams are basically a broken version of a warn system. Agreed.
2023-07-14 20:39:35 -07:00
fowr
5ef004c7ad remove telegrams 2023-07-15 00:24:04 -03:00
RealAngeleno
715e73ae90
link to stable download 2023-07-13 22:29:52 -07:00
RealAngeleno
972bc855b8
Merge pull request #596 from vichan-devel/RealAngeleno-patch-8
Fix oversight in hide_filename
2023-07-13 22:22:59 -07:00
RealAngeleno
899cfe1aaa
Fix oversight in hide_filename 2023-07-13 22:11:59 -07:00
RealAngeleno
485862acaa
Merge pull request #593 from vichan-devel/RealAngeleno-patch-5
Modify email field and selectbox functionality
2023-07-10 04:05:45 -07:00
RealAngeleno
f48872d5a4
prohibit emails from showing up in api if hide_email is true 2023-07-10 04:02:51 -07:00
RealAngeleno
694351baa8
fix email logic and add nonoko setting to selectbox
Changes it so that if the user is mod and they can bypass fields, "email" will show up just fine. If not, "email" will become an options field, like on 4chan. The options field will show up for anybody if hide_email is set to true.
Nonoko will be in the selectbox if always_noko is set to true.
2023-07-10 03:39:34 -07:00
RealAngeleno
e2a42c67f6
Merge pull request #592 from vichan-devel/RealAngeleno-patch-4
prohibit original filename from showing up in api when disabled
2023-07-10 02:47:10 -07:00
RealAngeleno
ed627325ad
prohibit original filename from showing up in api when disabled
Makes it so that if $config['show_filename'] = false, it will show $apiPost['tim'] as the filename instead.
2023-07-10 02:46:28 -07:00
RealAngeleno
33397fa1cf
That Rizon chat was KIA 2023-07-09 17:38:31 -07:00
RealAngeleno
3c2f1800ec
Merge pull request #587 from vichan-devel/RealAngeleno-patch-8
Add hide-form.js.
2023-06-26 15:06:22 -07:00
RealAngeleno
eaf7c83e15
Create hide-form.js 2023-06-26 15:05:51 -07:00
RealAngeleno
e912ee24ec
Merge pull request #585 from vichan-devel/RealAngeleno-patch-5
Change variable for max lines to prevent conflict
2023-06-25 05:27:10 -07:00
RealAngeleno
5df3ae6606
Update post.php 2023-06-25 05:26:29 -07:00
RealAngeleno
728476ce99
Update config.php
prevent conflict
2023-06-25 05:25:32 -07:00
RealAngeleno
0dd904aec5
Merge pull request #583 from vichan-devel/RealAngeleno-spaceless
(twig) Remove spaceless for post and file descriptions
2023-06-23 01:21:27 -07:00
RealAngeleno
744b025137
Merge pull request #584 from vichan-devel/RealAngeleno-patch-4
add missing break in switch/case for dismiss post
2023-06-22 04:50:31 -07:00
RealAngeleno
691ce02cbd
add missing break in switch/case for dismiss post
fixes bug in which Dismiss Post worked identically to Dismiss+
2023-06-22 04:49:22 -07:00
RealAngeleno
222de51247
remove spaceless filter for post description 2023-06-21 15:57:39 -07:00
RealAngeleno
0470064ea6
Update post_thread.html 2023-06-20 16:38:59 -07:00
RealAngeleno
07f998f9eb
Merge pull request #582 from ogjamesfranco/ogjamesfranco-patch-1
fix incorrect function call in body length check
2023-06-20 16:00:30 -07:00
James Franco
d8732d3d30
fix incorrect function call in body length check 2023-06-17 22:20:05 -05:00
RealAngeleno
1a39025162
Merge pull request #578 from vichan-devel/RealAngeleno-patch-3
make it so that appeals always go through post.php
2023-06-01 23:24:27 -07:00
RealAngeleno
fbee2dfbe0
make it so that appeals always go through post.php
Originally, appeals would not go through if made through banned.php, so routing everything through one place.
2023-06-01 23:24:09 -07:00
RealAngeleno
81d56bb784
Merge pull request #577 from vichan-devel/RealAngeleno-patch-8
changed language in audit log
2023-05-28 19:30:20 -07:00
RealAngeleno
2cd1ea4095
changed "his" to "their"
also inadvertently made vichan woke
2023-05-28 19:29:26 -07:00
RealAngeleno
39f4f5cd0b
Merge pull request #576 from syogu/patch-1
A small typo
2023-05-27 19:32:23 -07:00
mikka
6a13e1053d
A small typo 2023-05-26 22:54:32 +02:00
RealAngeleno
1504a30e45
Merge pull request #575 from vichan-devel/revert-574-RealAngeleno-patch-5-1
Revert "update Yotsuba B for parity with 4chan"
2023-05-23 01:29:52 -07:00
RealAngeleno
7d95959735
Revert "update Yotsuba B for parity with 4chan" 2023-05-23 01:28:51 -07:00
RealAngeleno
b112201d2b
Merge pull request #574 from vichan-devel/RealAngeleno-patch-5-1
update Yotsuba B for parity with 4chan
2023-05-23 01:20:07 -07:00
RealAngeleno
0799b5399b
Merge pull request #573 from vichan-devel/RealAngeleno-patch-5
Fix parity issues with the yotsuba theme
2023-05-21 10:09:54 -07:00
RealAngeleno
ec8bb62764
update Yotsuba B for parity with 4chan 2023-05-21 00:19:18 -07:00
RealAngeleno
5d1d52295a
parity 2023-05-21 00:10:09 -07:00
RealAngeleno
77f4684a6b
Merge pull request #572 from vichan-devel/RealAngeleno-patch-4
allow posts to be discarded for containing too many lines
2023-05-20 15:40:20 -07:00
RealAngeleno
bb59e907b1
allow posts to be discarded for too many lines 2023-05-20 15:38:40 -07:00
RealAngeleno
727e8723f0
add too many lines 2023-05-20 15:37:25 -07:00
RealAngeleno
d04e0d2caa
Update config.php 2023-05-20 14:45:26 -07:00
RealAngeleno
1db892fa6d
undid the undo 2023-05-20 11:31:07 -07:00
RealAngeleno
bdfd967554
revert README until all issues are sorted out 2023-05-19 23:40:23 -07:00
basedgentoo
ef32749986
No longer Kolyma-Affiliated. 2023-05-19 20:47:33 -04:00
RealAngeleno
d636076597
Merge pull request #569 from vichan-devel/RealAngeleno-patch-3
add some information about the requirement for boardlinks in auto-reload
2023-04-28 22:37:06 -07:00
RealAngeleno
380c3ba000
add some information about the requirement for boardlinks to be enabled for the script to work 2023-04-28 22:36:11 -07:00
RealAngeleno
a2d9493602
undid since I wanted to do it with a PR 2023-04-28 22:35:25 -07:00
RealAngeleno
639785cd43
Added some small information about the requirement for boardlinks for script to load 2023-04-28 22:33:52 -07:00
basedgentoo
d1d324fc81
README update & delete unapplied patches directory. (#566)
* We merged this.

No need for this anymore.

* Update README

No more unapplied patches, we also are doing releases now.
2023-04-25 04:36:28 +00:00
RealAngeleno
b0445d8b61
Merge pull request #565 from vichan-devel/RealAngeleno-patch-2
fix error with the newer version of twig
2023-04-24 16:29:59 -07:00
RealAngeleno
144f0e1a3d
fix error with this version of twig
Caught fatal error: Uncaught Twig\Error\SyntaxError: Unexpected token "name" of value "group_name" ("name" expected with value "from").

done on
PHP 7.2
Apache
2023-04-24 16:28:49 -07:00
RealAngeleno
d1724d0da6
Merge pull request #563 from vichan-devel/revert-561-revert-560-dismiss_report
Undo temporary revert of a merge
2023-04-23 19:17:05 -07:00
RealAngeleno
66be6de2fd
Revert "Temporarily Revert "feature: dismiss all reports for a post" (misclick)" 2023-04-23 19:15:44 -07:00
basedgentoo
8012cc5f05
Merge pull request #527 from discomrade/regex-open-bracket
Allow open parentheses before cite: "(>>1"
2023-04-23 22:13:18 -04:00
basedgentoo
417406d970
Merge pull request #553 from perdedora/update_twig
Update twig to 2.9
2023-04-23 22:12:49 -04:00
RealAngeleno
f926d6c399
Merge pull request #561 from vichan-devel/revert-560-dismiss_report (misclick)
Temporarily Revert "feature: dismiss all reports for a post" (misclick)
2023-04-23 19:04:32 -07:00
RealAngeleno
aee8288942
Revert "feature: dismiss all reports for a post" 2023-04-23 19:04:01 -07:00
RealAngeleno
b3c6896e1b
Merge pull request #560 from perdedora/dismiss_report
feature: dismiss all reports for a post
2023-04-23 19:03:55 -07:00
fowr
d825c36b8d feature: dismiss all reports for a post 2023-04-23 22:07:16 -03:00
RealAngeleno
f8c8d57d64
Merge pull request #550 from f89s/master
Fix combining character set, allow limit for combining characters
2023-04-22 09:31:06 -07:00
fowr
87f99715c9 Merge branch 'master' of github.com:perdedora/vichan into update_twig 2023-04-21 00:05:20 -03:00
RealAngeleno
c2eaa69013
Merge pull request #557 from vichan-devel/RealAngeleno-patch-1
change copyright to current year
2023-04-12 13:53:52 -07:00
RealAngeleno
b1e428bed7
change copyright to current year 2023-04-12 13:51:29 -07:00
fowr
b6c8b05cf7 change the default of twig_auto_reload to false 2023-03-30 17:52:38 -03:00
Yuri Kuznetsov
05851f950e
Merge pull request #552 from perdedora/fix_confirm_page
Add global to mod_confirm
2023-03-30 16:31:44 -04:00
basedgentoo
76c5f77932
Merge pull request #555 from vichan-devel/timeline
[timeline] Actually wait, it's even more complicated than that.
2023-03-29 21:21:35 -04:00
Fredrick Brennan
ddae472dd1 [timeline] Make 4chan the head of the tree 2023-03-29 21:17:25 -04:00
Fredrick Brennan
db68297f58 [timeline] Actually wait, it's even more complicated than that. 2023-03-29 21:00:24 -04:00
basedgentoo
4e383426bf
Merge pull request #554 from vichan-devel/timeline
[README] Add timeline
2023-03-29 20:36:56 -04:00
Fredrick Brennan
fc00b08c80
[README] Add timeline 2023-03-29 20:26:38 -04:00
fowr
427f3f8a0a delete remove_whitespace filter 2023-03-29 19:13:28 -03:00
fowr
d2bb450b1a update twig to 2.9 2023-03-29 18:59:28 -03:00
fowr
2c847a6413 add global to mod_confirm 2023-03-29 18:20:10 -03:00
f89s
90bf50fa30 Fix combining character set, allow limit for combining characters 2023-03-28 19:01:12 +04:00
Yuri Kuznetsov
08c9929eb0
Merge pull request #548 from basedgentoo/master
Add Twemoji submodule.
2023-03-25 01:20:30 -04:00
basedgentoo
19c15325b7 Add Twemoji submodule. To use: git submodule init && git submodule update 2023-03-25 01:15:47 -04:00
Yuri Kuznetsov
448d506135
Merge pull request #547 from basedgentoo/basedgentoo-twemoji-issue
This should've been a submodule.
2023-03-25 00:45:50 -04:00
basedgentoo
a93a2dc869
This should've been a submodule. 2023-03-25 00:42:34 -04:00
runit
573dfa84e3 Add Twemoji JavaScript Library 2023-03-25 00:21:06 -04:00
kuz-sysadmin
f9db8e05de
Fixed maintainer list
To look more like past entries, removed unecessary note. 

We will keep e politics out of the github.
2023-03-24 04:30:04 -04:00
basedgentoo
dc7668df64
URL error 2023-03-24 04:22:43 -04:00
basedgentoo
686dc80644
Hopefully final update to the readme for now. 2023-03-24 04:21:43 -04:00
basedgentoo
95d73ae6f9
Update README.md 2023-03-24 03:53:05 -04:00
basedgentoo
324e2f6af4
Update README.md 2023-03-24 03:03:09 -04:00
basedgentoo
e0e8ea50a9
Update README.md 2023-03-24 01:41:49 -04:00
basedgentoo
f3f6d2aa2d
Professionalism! 2023-03-24 01:37:12 -04:00
basedgentoo
9d460d5b0a
Update README 2023-03-24 01:36:25 -04:00
RealAngeleno
f631b83fb1 fix issues with the banner script not working
PHP 7.4
Notice: Trying to access array offset on value of type resource in on line 13

Notice: Trying to access array offset on value of type resource in on line 14

Notice: fpassthru(): read of 8192 bytes failed with errno=21 Is a directory in  on line 17
2023-03-09 01:17:09 -05:00
Fred Brennan
a69337e243 Apply inc/display.php@0a2dfed from vichan/infinity 2023-01-24 02:35:15 -05:00
Fredrick Brennan
491f71ce3a
[README] +webservers/PHP exp needed to use in 2023 2023-01-20 22:39:24 -05:00
discomrade
85b5dee77d Fix post number on dismissed reports log, show id
Previously the report dismiss logs would show the report id instead of the post number.
2023-01-20 22:36:36 -05:00
fowr
2d708984c4 fix: vichan ban length post variable is different than npfchan. causing the ban to be always permanent 2023-01-14 19:22:04 -05:00
perdedora
b02a1fc0db
feat: edit pre-existing bans (#528)
* feat: edit pre-existing bans

* change default permission

* theres no need for elseif here. related: d34f083a6b33185927c6b79a38477f4ea4ce49b5

* quote href param

* changes made
2023-01-12 20:38:23 -05:00
fowr
46b29de7ff remove requires since we are using autoload and its broken 2023-01-12 15:33:33 -05:00
Fred Brennan
fe3e4997b6 +static/unapplied patches 2023-01-12 05:37:21 -05:00
Fredrick Brennan
3256049ca9
[README] + § Unapplied patches 2023-01-12 05:30:08 -05:00
discomrade
5d31f3bab7
Add open parentheses to cite regex
Allows cite regex to match a post number after an opening parenthesis. "I like the comfy threads (>>1 and >>2) because they're comfy"
From d78254b41d
2023-01-12 10:16:15 +00:00
discomrade
2317c0adee Add default value for flood_cache
The original code left flood_cache undefined, leading to errors in newer versions of PHP. See https://github.com/vichan-devel/vichan/issues/525
2023-01-12 03:30:23 -05:00
Majin Bejitto
23163ae59c fix "scandir should not need to sort in b.php (banner code)"
scandir by default sorts files in ascending order. this is unnecessary when you're picking a random file anyway. it's just wasting CPU cycles and increasing latency as more files are added.

currently it is

    $files = scandir($dir);

it should be

    $files = scandir($dir, SCANDIR_SORT_NONE);
2022-12-21 03:36:45 -05:00
Majin Bejitto
a0f699d49f fix "anchor/bumplock icon won't show up without fixing variable name"
mistake in /templates/post_thread.html

it should be post.sage not post.bumplocked, there is no bumplocked field in posts_X tables
2022-12-21 03:36:35 -05:00
Fredrick Brennan
70222e8c2d Revert "When moving Reply from Thread to Thread: Remove re-direct to error page "Thread does not exist"" 2022-12-14 03:18:00 -05:00
27chan
5961373dda
Merge pull request #518 from smolten/master
When moving Reply from Thread to Thread: Remove re-direct to error page "Thread does not exist"
2022-12-13 17:31:36 -03:00
smolten
812a111107 When moving a post, add condition (post is Thread) before trying to make Thread for post. Removes "Thread Does not exist" page that showed up even when a post was successfully moved between threads. 2022-12-13 00:56:23 -07:00
Fred Brennan
191dbd3be0 [SECURITY] [REGRESSION] Fix config editor UI
Closes #516.

Co-Authored-By: Scotty Molt <smolt@asu.edu>
2022-12-10 10:27:59 -05:00
27chan
cd444a1c1b Update footer
Remove duplicate code footer in all pages
Updated the link to the project on github
2022-12-06 16:55:26 -03:00
perdedora
7571df84c8
break to avoid undefined error (#514) 2022-11-28 17:10:20 -05:00
deysu
c8f88c14a8
Add banners as default functionality & display them on mod login / dashboard when enabled (#513)
* Add banner support as a default, integrated option.
Used lainchan's original banner script, authored by barrucadu

* Display banners on moderator login and dashboard

* Remove memes & better directory structure
2022-11-17 01:48:24 -05:00
runit
f62acd5c1a banned.php now shows a pretty page instead of an ugly one. credits to JamesJDillon @ Lainchan 2022-10-15 10:09:10 -04:00
runit
4e5fecebd2 I didn't need to actually touch this. 2022-10-15 10:09:10 -04:00
runit
63b71bf1fc We're not Tinyboard anymore. We've been vichan for 8 years. We should reflect that.
Also use Github wiki so new enhancements can be reflected. It's better than linking to 10-year-old archived documentation.
I'll update the wiki eventually.
2022-10-15 10:09:10 -04:00
runit
b6d411c5e4 I'd just like to interject for a moment. 2022-10-15 10:09:10 -04:00
清靈語
5780e78975 Replace Google reCAPTCHA API's domain (#507)
This makes it accessible in mainland China.

Sources:
google/recaptcha#227
https://developers.google.com/recaptcha/docs/faq#can-i-use-recaptcha-globally
https://meta.stackoverflow.com/questions/402339/please-change-the-recaptcha-link-to-ensure-the-site-is-accessible-in-china

Co-Authored-By: Fredrick Brennan <copypaste@kittens.ph>
2022-10-15 10:07:10 -04:00
Fred Brennan
4c6a695a6f Use ENT_QUOTES when converting UTF-8 to HTML (#448)
Closes #448.
2022-09-15 14:46:05 -04:00
sshscp15
e42a1b04b1 fixes boardlist in catalog when in mod mode 2022-09-15 13:03:49 -04:00
sshscp15
30e7574649
Fix display warning/errors (#496)
* prevent filling debug param when debug is off

* fix php warning: "$item" must be passed by reference
2022-09-15 13:03:32 -04:00
sshscp15
401b506691 fix mod.php. check if key is there and is valid 2022-09-15 13:03:06 -04:00
27chan
70a06116e5
Update DEMO
Update version PHP
2022-09-12 20:18:18 -03:00
27chan
ec8ae76d43
Merge pull request #499 from vichan-devel/xss-embed
Removed regex with possibiblity of XSS
2022-09-05 13:59:45 -03:00
27chan
76fad44de4
Removed regex with possibiblity of XSS
An anonymous user reported the issue to me
2022-09-05 13:58:41 -03:00
Fred Brennan
572a11dba7 Flip insane default for non-developers 2022-08-29 11:48:38 -04:00
Fred Brennan
efd54a20e8 Install config to secrets.php by default 2022-08-29 11:47:47 -04:00
Fred Brennan
a99d7c7c80 Add support for APC(u) 2022-08-29 11:45:59 -04:00
C Hatfield
ae2d91c534
Moved hardcoded html filepaths into config file for extensibility (#354)
Co-authored-by: chatfield <chatfield@creatuity.com>
Co-authored-by: Fred Brennan <copypaste@kittens.ph>
2022-08-29 10:50:45 -04:00
haruhianon609
0f94915fdf
Add yandex images as image identification option (#430)
* Add yandex images as image identification option

* Update image_identification.html

* Fix indentation

Co-authored-by: Fred Brennan <copypaste@kittens.ph>
2022-08-29 10:37:40 -04:00
Fredrick Brennan
1e19e75bf5
Change illogical default of $config[force_body]
Makes JS and non-JS enforcement equivalent while providing a downgrade path.

JS may not allow empty bodies even when $config[force_body] false. Don't care enough to fix. PR welcome.

Close #493.
2022-08-29 10:30:50 -04:00
27chan
dd7c63b65f
Merge pull request #491 from vichan-devel/issue№441
fix mysql_version() for mariadb
2022-08-24 11:46:28 -03:00
Fredrick Brennan
9e63116338
fix mysql_version() for mariadb 2022-08-20 12:45:56 -04:00
Łiźnier Hełam Łabej
d6ea8db5ef
remove named parameters from call_user_func_array calls (#402) 2022-08-20 12:25:52 -04:00
sshscp15
4db4ab9cf0 simple catalog support for moderators 2022-08-20 12:25:10 -04:00
370chan
c170bc7ef2
Fix files not being saved in certain cases (#483) 2022-08-20 12:24:46 -04:00
PVNFU-28
b5eee58b96
Update theme.php (#409)
fixed hardcoded root that broke spoilered images on the catalog if vichan was not installed on the web root.
2022-08-20 12:21:42 -04:00
PVNFU-28
2d1420b763 Update style.css
Made CSS formatting more consistent, really minor stuff
2022-08-20 12:21:14 -04:00
PVNFU-28
75236d6ae5 Update functions.php
current regex consumes the space after a post quote, instead of merely checking that it's there. As a result textually consecutive post quotes, which the source calls cites, cannot be separated by a single space. This fixes that
2022-08-20 12:20:53 -04:00
ben2613
72f38933c2 Fix mobile browser hang issue when auto-reload by reducing DOM modification in forloop 2022-08-20 12:19:41 -04:00
bebyx
c128a37160
Fix editing global pages for 7.4 (#487) 2022-08-20 12:17:04 -04:00
Junicchi
23ebde7883 fix Undefined index ip problem, fixes #434 2022-08-20 12:13:02 -04:00
27chan
ae3b5b194c
Merge pull request #466 from discomrade/patch-5
Fix multiple issues in anti bump flood
2022-06-21 12:56:11 -03:00
27chan
1d8a577029
Merge pull request #440 from discomrade/patch-1
Fix custom thumb_ext when using ImageMagick convert
2022-06-06 22:06:16 -03:00
27chan
bfd0cc0bc2 Adjust css theme
Fix responsive
2022-06-01 11:46:28 -03:00
27chan
6577a0d9d8
Fix typo 2022-06-01 01:11:53 -03:00
27chan
023d6c763b
Updating information
Adding Redis in the recommendations section.
Inserting a demo section.
2022-06-01 01:09:05 -03:00
27chan
fe5b8b7863
Merge pull request #464 from discomrade/master
Fixes an error reporting typo in move thread.
2022-05-31 08:55:21 -03:00
rosemash
52321abc7b Fix 404 caused by recent_posts.html loading wrong JS filename 2022-01-22 13:55:08 -05:00
discomrade
77bab66293
Fix multiple issues in anti bump flood
- saged posts aren't ignored when finding last bump
- bumplocked thread with one reply, delete the reply and no post matches the query
- bumplocked threads should be ignored
2022-01-22 03:31:52 +00:00
jove
847c5d130c Fixes an error reporting typo. 2022-01-18 07:17:34 -01:00
discomrade
8512321669 Fix redis 'delete' deprecation error
Redis deprecated the 'delete' alias for 'del'. Posting while using redis cache would return an error, the post would still be posted.
2022-01-16 23:50:25 -05:00
Łiźnier Hełam Łabej
617f2a68da
Merge pull request #455 from vichan-devel/securimage
securimage captcha
2021-11-13 01:31:22 +01:00
h00j
a3dc72bddb securimage captcha 2021-11-13 01:24:34 +01:00
Fredrick Brennan
9745e9d854 Ignore recently added graphicsmagick check
Closes #445.
2021-11-03 22:55:55 -04:00
Fredrick Brennan
f1b43e5fb2 {% (end)?raw %}{% (end)?verbatim %}
```
rg '\{%\s*raw' -l | xargs -I{} sed -i -e 's/{%\(\s*\)raw/{%\1verbatim/g; s/endraw\(\s*\)%}/endverbatim\1%}/g' {}
```

Close vichan-devel/vichan#452.
2021-11-03 22:49:49 -04:00
h00j
4fd93f490f add sischan style, adjust boardlist/options background 2021-08-08 18:46:44 +02:00
discomrade
54cd4d41f2
Fix custom thumb_ext for ImageMagick convert
Fixed breaking typo in previous commit
2021-06-23 12:40:27 +00:00
discomrade
a752a3930c
Fix custom thumb_ext for ImageMagick convert
When using ImageMagick's convert tool, the output defaults to the input format if no file extension or format is specified.
The temp file currently has no extension, so a $config['thumb_ext'] value has no effect on the image.
By appending the thumb_ext to the temp output file, it will convert the image to the intended format.

You can see this issue present on lainchan, where thumbnails have a .png filename but are not really PNG files when the input is a .jpg, for example.
2021-06-23 11:52:29 +00:00
h00j
fd9a3c07dd Merge branch 'master' of https://github.com/vichan-devel/vichan 2021-04-01 22:30:49 +02:00
h00j
281dccb690 fix undefined index in cloak_mask/uncloak_mask 2021-04-01 22:30:22 +02:00
27chan
61d6132bb3 Fix post.php
I believe that you ended up closing some functions by mistake and then gave the following error when making a post:

PHP message: PHP Parse error:  syntax error, unexpected '}', expecting end of file in /var/www/vichan/html/post.php on line 462
2021-03-17 20:40:26 -04:00
Łiźnier Hełam Łabej
5a027781cc
Merge pull request #423 from vichan-devel/telegrams
add telegrams
2021-03-12 22:07:42 +01:00
h00j
064deec26f fix date 2021-03-12 21:55:27 +01:00
h00j
8002455061 important.html relative time 2021-03-12 21:54:31 +01:00
h00j
f43b5ffbc4 woops 2021-03-12 21:53:16 +01:00
h00j
59c0f788d2 typo 2021-03-12 21:52:37 +01:00
h00j
4ef7feabf2 add telegrams 2021-03-12 21:51:42 +01:00
h00j
8decd4f73f backlinks on ukko are fine 2021-03-04 15:09:52 +01:00
Łiźnier Hełam Łabej
ee57b6b5ca
Merge pull request #405 from PVNFU-28/patch-3
Update config.php
2021-02-26 21:41:46 +01:00
Łiźnier Hełam Łabej
7a44731f27
Merge pull request #413 from PVNFU-28/patch-9
replace rbl.efnet.org with rbl.efnetrbl.org
2021-02-26 21:40:01 +01:00
Łiźnier Hełam Łabej
35068d221b
Merge pull request #412 from isaacimran/patch-1
Update recent_posts.html
2021-02-26 21:36:59 +01:00
Łiźnier Hełam Łabej
2772891486
Merge pull request #411 from PVNFU-28/patch-8
Update config.php
2021-02-26 21:36:00 +01:00
PVNFU-28
d166db6a50
replace rbl.efnet.org with rbl.efnetrbl.org
rbl.efnet.org redirects to rbl.efnetrbl.org and says
"Notice We have created a mirror of the rbl.efnet.org zone at rbl.efnetrbl.org.
It has the exact same data and responses. Please use the mirror in your configs.
The mirror was created after repeated failures at Network Solutions."

Also deleted some random tabs on empty lines and some extra spaces which were put by error I guess
2021-02-21 01:03:10 -03:00
Mert Kasım İmran
3e5e9bdae5
Update recent_posts.html
Fixes #406
2021-02-20 20:11:35 +03:00
PVNFU-28
30eb4e8335
Update config.php
Fixes https://github.com/vichan-devel/vichan/issues/404
2021-02-16 23:33:52 -03:00
Łiźnier Hełam Łabej
3242e28b19
Merge pull request #407 from vichan-devel/composer
update authors in composer.json
2021-02-14 10:22:46 +01:00
h00j
a8e455b014 update authors 2021-02-14 10:20:10 +01:00
h00j
e9e5128604 fix cli tools 2021-02-14 09:22:44 +01:00
h00j
00349d0315 mute constant redefinition notice 2021-02-14 09:22:01 +01:00
panfu28
c25e3dea78
Update config.php
Fixed embedding for dailymotion, metacage and vocaroo.
Google Videos stopped being a thing in 2012 it seems.
2021-02-14 02:49:15 -03:00
h00j
7d855c5316 fix require's 2021-02-13 21:30:27 +01:00
h00j
e405a6c676 fix install script 2021-02-13 21:23:07 +01:00
h00j
908b843854 move antibot functions 2021-02-13 21:14:06 +01:00
Łiźnier Hełam Łabej
d5e8747a19
Merge pull request #401 from vichan-devel/composer
use composer
2021-02-13 19:52:00 +01:00
h00j
0daf03c360 update README 2021-02-13 19:37:18 +01:00
h00j
5b7fb87ec1 add required extensions to composer.json 2021-02-13 19:37:00 +01:00
h00j
599fee5e21 use composer 2021-02-13 19:24:03 +01:00
Łiźnier Hełam Łabej
47df9c6485
Merge pull request #399 from vichan-devel/ip-cloaking
ip cloaking
2021-02-13 17:28:30 +01:00
Łiźnier Hełam Łabej
40d1cea043
Merge pull request #391 from panfu28/patch-3
Update index_fs.css
2021-02-13 17:28:05 +01:00
Łiźnier Hełam Łabej
1843f4a265
Merge pull request #390 from panfu28/patch-2
Update index.css
2021-02-13 17:27:41 +01:00
Łiźnier Hełam Łabej
20ce4a314e
Merge pull request #389 from panfu28/patch-1
Update config.php
2021-02-13 17:27:25 +01:00
h00j
bce71c1f98 ip cloaking 2021-02-13 14:11:41 +01:00
h00j
7a42158177 add maintainer timeline to README 2021-02-09 10:53:34 +01:00
h00j
e7d29cdba9 update irc channel 2021-02-07 00:51:17 +01:00
h00j
4f87eb5d52 update README 2021-02-07 00:48:27 +01:00
panfu28
4070e82ae4
Update index_fs.css
More consistency fixes
Is this type of PR allowed? I just see small errors or inconsistencies all over the place and can't help but want to make the code look and read better.
2020-12-11 23:12:08 -03:00
panfu28
f91cbc16f8
Update index.css
Fixed some errors and replaced lines started with 4 spaces for a tab, some lines started with a tab already so why not make it consistent.
2020-12-11 23:02:44 -03:00
panfu28
d8e3925183
Update config.php
just fixed a comment that might confuse new users, plus it was outdated
2020-12-11 17:10:43 -03:00
Mert Kasım İmran
d6d1082991 Fix for title/subtitle related issue
Subtitle was the page title and title was unused.
2020-12-02 15:56:35 -05:00
Fredrick Brennan
d7d478181d
Update README.md
not offering paid support right now
2020-11-13 16:05:04 -08:00
Sardach
19151def82 insignificant fix
PHP7 shows a warning when executing tools/rebuild2.php: "Declaration of case-insensitive constants is deprecated"
$group_name and $group_value really not need be case-insensitive, so i simply removed that "true".
2020-10-31 04:24:21 -07:00
papereth
6ccaf19045
Fixed thread.html template (#380)
* Update functions.php

` $_SERVER['REMOTE_ADDR']` was hardcoded in ban lookup instead of `$ip` variable

* Fix information leak in thread.html

Sensitive information can be leaked due to inadequate/absent escaping.

Line 14 is truncating before removing tags, this can cause some tags to be cut and therefore not be removed by the `remove_` functions.
Line 22 is just leaking it all, not removing anything.

* Fixed thread template

`remove_markup` is not available on vichan, arguably it makes things better but it's out of scope for this CHANGE, removing modifiers is enough to stop the info leak
consider adding it again after pulling:
fallenPineapple@a5b3336

also moving truncation before escaping for extra safety
2020-08-15 07:19:47 -07:00
papereth
2275735fdf
Fix information leak in thread.html (#377)
Sensitive information can be leaked due to inadequate/absent escaping, if proxy_save enabled

Line 14 is truncating before removing tags, this can cause some tags to be cut and therefore not be removed by the `remove_` functions.
Line 22 is just leaking it all, not removing anything.
2020-08-10 09:50:02 -07:00
Eman Gamer
cf6a733931
Fix Capitalization on setUpControl for Chromium (#378)
Chromium browsers expect capital U in setUpControl and old version of webm-settings.js has setupControl which causes a error and makes expand-video.js not work and options.js not save when this is in use. This bug is not present on FireFox which automatically fixes this for some reason. Stupid bug, stupid fix. No lines actually added or removed.
2020-08-09 19:25:33 -07:00
papereth
a268004c7a
Fix wrong variable used in ban lookup (#376)
` $_SERVER['REMOTE_ADDR']` was hardcoded in ban lookup instead of `$ip` variable
2020-08-09 18:31:50 -07:00
Fredrick Brennan
01538ed33a Close #366
I don't know why this works, but this extra whitespace is required on
PHP 7.4.

If you want to know why I hate PHP updates, this is why.
2020-01-21 09:46:29 +08:00
Daniel Saunders
2600298be8 Theme fixes 2020-01-20 10:37:54 +08:00
Daniel Saunders
c7e5cd6814 $board can be NULL here, prevent indexing it
Simplest 7.4 fix ever? Possibly.
2020-01-20 10:37:10 +08:00
Fredrick Brennan
5e809047ad By default, no longer treat deprecations as errors
Close #363.

See also https://www.youtube.com/watch?v=9crnlHLVdno
2020-01-20 10:04:39 +08:00
Fredrick Brennan
a2ba03849f Fix PHP 7.4 deprecations 2020-01-20 10:04:39 +08:00
Fredrick Brennan
af06cf3737
Disable check_updates by default
It no longer works and never will again, so...
2020-01-15 11:36:51 +08:00
rarjpg
63b0b92690 Move HTML Tidy 'bare' option to the config 2019-11-29 19:21:20 +08:00
rarjpg
0a3bca7dd8 Various fixes 2019-11-29 13:54:08 +08:00
Kureva
1613f6baea Option to reset thread bump after last post deleted. 2019-10-14 18:56:13 +08:00
Fredrick Brennan
9fdbc6c1f0
clarify previous commit 2019-09-22 18:58:10 +08:00
Fredrick Brennan
1173f86869
You can now pay for support 2019-09-22 18:54:50 +08:00
Daniel Saunders
e15e966cdb Fix a bug related to deleting boards (see https://github.com/vichan-devel/vichan/issues/331) 2019-09-22 16:57:12 +08:00
Fredrick Brennan
3a41c24e6e Fix PHP 7.3 regression in ?/users
This gets rid of the "Case-insensitive constants are deprecated" error
by passing doing |upper before passing to constant().
2019-05-02 12:19:50 +08:00
Fredrick Brennan
23378e2623
Remove refs to abandoned domains; IRC channels 2019-04-19 12:23:47 +08:00
Fredrick Brennan
47e4af1eb1 Moved to vichan-devel/vichan wiki
I decided it made more sense to put these in our wiki than to distribute
them with vichan, so right after I added them I removed them.

They can now be read at https://github.com/vichan-devel/vichan/wiki -
and checked out from https://github.com/vichan-devel/vichan.wiki.git
2019-04-18 20:20:38 +08:00
Amsemy Teladi
14384ba1ee Fix docs 2019-04-18 19:52:50 +08:00
Amsemy Teladi
a99c45de22 Save Tinyboard docs (2012-10-16) from web.archive.org 2019-04-18 19:52:50 +08:00
Brayden
997326af59 fix typo in inc/config.php 2019-03-22 10:02:38 +08:00
Circlepuller
dd5dbe65c7 Close #293 2019-03-09 11:54:18 +08:00
Fredrick Brennan
bcfb39bde8
remove superfluous ``and" 2018-11-21 13:37:33 +08:00
Fredrick Brennan
e0e0edc885
not anymore lol 2018-11-21 13:37:00 +08:00
Fredrick Brennan
84bb3833a6
add fact unix is required to readme 2018-11-21 13:35:57 +08:00
Fredrick Brennan
7514f31b36 count➜length in confeditor for PHP7.2 2018-10-12 14:47:38 +08:00
Fredrick Brennan
a2f938c814
Merge pull request #310 from H1K1CH4N/master
Adds a new theme called "Index"
2018-10-12 14:39:35 +08:00
H1K1CH4N
b1842dfe10 removed NPFchan copyright 2018-09-29 04:19:36 +02:00
H1K1CH4N
6f15b56b65 made the image header a little bit better in index theme 2018-09-27 04:58:05 +02:00
H1K1CH4N
44dcbca6c9 improved index theme css 2018-09-27 03:02:21 +02:00
H1K1CH4N
b8f1c219f0 Adds a new theme called "Index"
adds an option to use textarea in theme settings.
Merged most Basic, Recent and Frameset theme functions in one.
you can add a video picture icon and quote in the homepage.
@ctrlcctrlv feel free to add suggestions and fix bladly formed code or let me know and I will try to fix.
i installed it on my demo site: https://hikichan.com/
2018-09-27 00:41:22 +02:00
Fredrick Brennan
a510ebcab9
Remove "Donations" section, add note about php7.2 2018-09-18 14:15:41 +08:00
Fredrick Brennan
aeb4a31194 Close #304 2018-09-18 14:08:06 +08:00
Fredrick Brennan
f6cc993bce
Update README.md
+and other serious bugs
2018-08-08 18:51:56 +08:00
Fredrick Brennan
ac971f36d5 Fix capcodes in PHP7.2. Close #299 2018-07-27 20:08:03 +08:00
Fredrick Brennan
41cfd500de Fix dashboard Countable on non-countable error
Only affected PHP7.2, was due to a sloppy template. PHP7.2 is much more
strict than previous versions so these kinds of bugs are coming to the
fore.
2018-07-27 19:40:44 +08:00
Fredrick Brennan
be2eafd4fc Fix reports under PHP7.2
You'll need to delete all reports made before applying this patch for it
to work right. However, all reports made after applying this patch will
appear correctly in `mod.php?/reports`.

This closes #300.
2018-07-27 19:40:32 +08:00
Fredrick Brennan
524d48110b Fix bans of form "5d", "1y", etc. for PHP7.2
This closes #301.
2018-07-27 19:06:31 +08:00
Fredrick Brennan
814b9246d4 Fix broken link in install.php 2018-07-27 18:48:27 +08:00
Fredrick Brennan
0aa4e3badc Update Twig. This closes #295 2018-05-10 18:25:37 +08:00
Fredrick Brennan
b078ffb1e4 Close #282 2018-05-10 17:33:07 +08:00
Fredrick Brennan
ce72d9c8ee
Merge pull request #287 from antedeguemon/master
Update license and copyright dates
2018-03-02 14:55:56 +00:00
antedeguemon
b94bf5ec19 Update license and copyright dates 2018-03-01 22:57:53 -03:00
Fredrick Brennan
693fa1bdfa Fix #284 for new installations _only_
Users with existing installations are still required to follow the
advice in security bulletin #284.

This commit isn't perfect -- PHP installations below 7.0 and w/o OpenSSL
cannot be fully secured in my estimation. . .
2018-01-29 18:19:16 +08:00
Fredrick Brennan
6ae0f45c31
warn against new vichan installations 2018-01-23 18:57:25 +08:00
Fredrick Brennan
d55721d033
add my email to README for security problems 2018-01-15 22:18:17 +08:00
H0K4
b3e16cfa0d fixed banned redirect i think (#270)
* fixed banned redirect i think

my tinyboard script has been altered a lot but i think this is the fix for the wrong ban redirect.

* maybe it's just this
2017-11-06 20:19:35 +08:00
Fredrick Brennan
464d3b4a04
Merge pull request #269 from H0K4/patch-1
Prevents multiple submit/copy when moving a thread/reply.
2017-11-06 11:21:51 +08:00
H0K4
e8edadeda9
Update move.html 2017-11-05 18:07:52 +01:00
H0K4
896d9e2f75
Update move_reply.html 2017-11-05 18:07:22 +01:00
H0K4
714cb95194
Update move_reply.html 2017-11-05 18:04:34 +01:00
H0K4
767e8f5d6a
Prevents double submit when moving a thread.
I probably moved 1000 of threads and if you double click on the submit button it duplicates the moved thread.
2017-11-05 18:03:20 +01:00
Fredrick Brennan
c2f7073dd4 Fix warnings in PHP7 in gettext library
Not sure how to commit this upstream, the library seems to be
unmaintained.
2017-11-05 21:17:20 +08:00
Fredrick Brennan
ac8f15f0f2 Close #267 2017-11-05 16:25:02 +08:00
Fredrick Brennan
8e811cec44 Close #265 2017-11-03 22:12:35 +08:00
Fredrick Brennan
b7a3bde4c8
Merge pull request #264 from deysu/patch-1
Remove links to (dead) tinyboard.org
2017-11-02 15:39:51 +08:00
Christopher Henly
598843547e
Remove links to (dead) tinyboard.org
Instead we link to the archived documentation, just like in README.md. I also removed the link to tinyboard.org from the boardlinks example, and replaced it with a Github one.
2017-10-30 15:20:43 -04:00
Fredrick Brennan
6cc68ffdc8
Merge pull request #262 from antedeguemon/patch-1
New vimeo embed code
2017-10-28 10:57:36 +08:00
vi
8c0b413c94
New vimeo embed 2017-10-27 22:41:08 -02:00
Fredrick Brennan
09b373cf60 Merge pull request #245 from ghost/patch-2
Bug fixing inc.
2017-10-26 13:35:26 +08:00
Fredrick Brennan
74283b131d Merge pull request #259 from RalphORama/master
Use random_bytes if PHP version >= 7.1.0
2017-10-26 13:27:30 +08:00
RalphORama
c8765dede4 Update PHP version check
Removed trailing zero
2017-10-24 17:36:14 -04:00
RalphORama
2097562596 PHP version check for mcrypt_create_iv
Use `mcrypt_create_iv()` if PHP version is less than 7.1.0, otherwise use `random_bytes()` (introduced in PHP 7.1 to replace `mcrypt_create_iv()`)
2017-10-24 16:27:00 -04:00
RalphORama
67b1565ef8 Replace mcrypt_create_iv with random_bytes
`mcrypt_create_iv()` was deprecated in PHP 7.1.0.
2017-10-24 16:16:25 -04:00
j147
7477215eee Merge pull request #247 from antedeguemon/master
Bugfixes: edit post page minor fix and install.php bug
2017-10-01 21:31:13 +02:00
j147
f25c641278 Merge pull request #248 from roIyat/patch-1
Update thread-watcher.js
2017-10-01 21:29:39 +02:00
j147
617dbb1711 Merge pull request #257 from ev1l0rd/patch-1
Minor error fix for upgrades from 5.1.3 or earlier
2017-10-01 21:28:53 +02:00
Valentijn
be651829e7 Minor error fix for upgrades from 5.1.3 or earlier
Closes #256 and #199.

Full credit for locating the fix goes to @LZZZZ.
2017-10-01 20:14:52 +02:00
antedeguemon
b766b958d1 Fix: cache flushing to avoid installation error 2017-08-02 00:38:23 -03:00
roIyat
7aeac11460 Update thread-watcher.js
A watch thread button is now placed before reply button so citation links don't go between them.
2017-07-30 02:57:39 +02:00
antedeguemon
4d1dc45a7c Bugfix: allow mods to edit poster name at edit post page 2017-07-29 20:23:18 -03:00
Thalis
7529c83a00 added fix from @Circlepuller to mod_move_reply also
thx @Cirlepuller
2017-07-28 22:51:59 +02:00
Thalis
0846d0c784 might fix moving replies with deleted image
brace yourself for other conflicts lol
2017-07-28 22:41:20 +02:00
Thalis
0b84fc26d6 fixed deleted.png image not found on the front end 2017-07-28 21:40:06 +02:00
Thalis
7883998a78 should fix moving a spoilered thread (OP) image 2017-07-28 21:01:12 +02:00
czaks
d5ee60009f downgrade jquery to 2.2.4 2017-07-26 23:44:49 -04:00
czaks
b7875be471 search form in index: fix order 2017-07-26 23:37:05 -04:00
czaks
1371b64986 undo the reason limit 2017-07-26 21:37:08 -04:00
Marcin Łabanowski
19cb514ebb Merge pull request #242 from 27chan/master
Error in report
2017-07-27 03:25:30 +02:00
27chan
899a98c503 Fix error in report threads and replys 2017-07-26 22:22:34 -03:00
27chan
98cb2725eb Merge pull request #1 from vichan-devel/master
Update to 5.1.4
2017-07-26 22:13:29 -03:00
Marcin Łabanowski
ced2b3814e Merge pull request #241 from Circlepuller/master
Updated to reCAPTCHA 2, added a new style, and fixed a JS bug.
2017-07-25 11:31:44 +02:00
Daniel Saunders
2a152b7ff1 Minor changes to form and boardlist in sharp.css 2017-07-25 02:29:52 -04:00
Daniel Saunders
504282b55f Merge remote-tracking branch 'vichan/master' 2017-07-24 22:40:39 -04:00
czaks
4025705eac replace faulty dnsbl with efnetrbl 2017-07-24 15:04:01 -04:00
Daniel Saunders
64cf4b11ee Dirty quick fix to allow moderation to move threads with deleted files 2017-07-24 15:01:17 -04:00
czaks
7b538f0eae Merge branch 'master' of github.com:vichan-devel/Tinyboard 2017-07-24 15:00:44 -04:00
Daniel Saunders
d8e12a15b7 Dirty quick fix to allow moderation to move threads with deleted files 2017-07-24 15:00:33 -04:00
Daniel Saunders
18aed77ecc urlencode reCAPTCHA response for safety 2017-07-24 13:24:44 -04:00
Daniel Saunders
1ad9f49694 Color fixes (sharp.css) 2017-07-24 13:03:12 -04:00
Daniel Saunders
04ce72f24b fuck go back 2017-07-24 12:57:10 -04:00
Daniel Saunders
9c3124177f Fixes to sharp.css including some cross-platform font support 2017-07-24 12:51:33 -04:00
Daniel Saunders
a31a3a281f Bug related to antispam and reCAPTCHA 2 valid fields 2017-07-24 12:22:53 -04:00
Daniel Saunders
09fadec620 inline-expanding.js needs jQuery to function, so why are we not including it in the default configuration too? 2017-07-24 04:38:38 -04:00
Daniel Saunders
b5fac28a8b Fully removed the outdated recaptchalib.php (freed up some room hehe) 2017-07-24 04:03:49 -04:00
Daniel Saunders
7a43a3ea34 Updated reCAPTCHA v2 to use api.js method 2017-07-24 03:40:56 -04:00
Daniel Saunders
78fb0a25a4 Added sharp.css 2017-07-24 03:23:29 -04:00
Marcin Łabanowski
39715e3595 Merge pull request #224 from ghost/patch-2
Implementing Czaks captcha
2017-07-23 17:57:59 +02:00
Marcin Łabanowski
59bcf88872 Merge pull request #146 from szalwia/master
Fix thumbnail scaling in recent theme
2017-07-23 17:55:40 +02:00
Marcin Łabanowski
3e23c028de Merge pull request #215 from antedeguemon/master
Prevents reports with too many characters
2017-07-23 17:55:22 +02:00
Marcin Łabanowski
daa922a239 Merge pull request #239 from bui/fix-search
fix search not remembering board
2017-07-23 17:54:26 +02:00
Marcin Łabanowski
ef1898833d Merge pull request #226 from ghost/patch-1
Fixed DNSBL TOR
2017-07-23 17:54:08 +02:00
Marcin Łabanowski
dc7e4d5b89 Merge pull request #240 from H0K4/patch-1
Board search implementation
2017-07-23 17:53:24 +02:00
Thalis
fe495fed64 Update config.php 2017-07-23 17:50:54 +02:00
Thalis
4efaf50c90 Board search content implementation
you can search boards with this mod.
2017-07-23 17:49:01 +02:00
Bui
1c4b67a597 fix search not remembering board 2017-07-07 23:35:38 +01:00
Marcin Łabanowski
d3cb413d6b Merge pull request #232 from miitroid/patch-1
New CSS: greendark.css
2017-06-28 14:03:57 +02:00
Z Blanche
0976a27cc4 New theme: greendark.css
Used on the /hentaiporn/ 8chan board.
2017-06-10 10:31:39 +00:00
Marcin Łabanowski
74ccc89e64 Merge pull request #230 from antedeguemon/master
Fixed XSS in post edit page and modsearch
2017-05-21 22:35:57 +02:00
antedeguemon
4f85b7c570 Fixed XSS in post edit page and modsearch 2017-05-21 17:08:43 -03:00
czaks
e672d490cd Merge branch 'master' of github.com:vichan-devel/Tinyboard 2017-05-17 14:56:21 -04:00
czaks
40fe35fedc early 404 staged 2017-05-17 14:54:35 -04:00
czaks
736e982945 [SECURITY] Lessen security impact
post.php: misc fixes
2017-05-17 14:05:01 -04:00
Hollick
29409f1456 Update config.php
Well I'm just putting this info out there for those that need tor protection. no reason to pull this if not stable.
2017-04-28 19:07:17 +02:00
Hollick
c4358b078e Update config.php 2017-04-28 16:19:32 +02:00
Hollick
bb86d55b1f Fixed DNSBL TOR
Don't know if Sectoor.de comes online again. Found this new dnsbl tor blacklist checker. in case you really need a tor blacklist.
2017-04-28 16:09:15 +02:00
Horija
e0f913a38f forgot Grave accents 2017-04-25 05:59:42 +02:00
Horija
dc7a507526 Update post.php 2017-04-24 12:21:33 +02:00
Horija
24491cf3c4 Update install.php 2017-04-24 11:51:26 +02:00
Horija
8b0c86d8bd Update install.sql 2017-04-24 11:49:38 +02:00
Horija
ce755b8b51 Update quick-reply.js 2017-04-24 11:46:00 +02:00
Horija
5dbfc0ab24 Update post_form.html 2017-04-24 11:44:39 +02:00
Horija
e94f25d4cd Add files via upload 2017-04-24 11:42:58 +02:00
Horija
e1bc4f1da9 Update config.php 2017-04-24 11:41:49 +02:00
Horija
3438718667 Add files via upload 2017-04-24 11:40:49 +02:00
Horija
6a53b99feb Create readme.md 2017-04-24 11:40:22 +02:00
Horija
9ddb5833b3 Implementing a new captcha
I'm (trying) to integrate @Czaks custom captcha
2017-04-24 11:38:56 +02:00
Marcin Łabanowski
29827d1ca4 Merge pull request #223 from Horija/patch-1
Fixed go to bottom link
2017-04-21 08:06:30 +02:00
Horija
175b54b7f0 Fixed go to bottom link 2017-04-21 03:09:48 +02:00
czaks
37eaea6312 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2017-04-07 13:07:30 -04:00
Marcin Łabanowski
a492e778af Merge pull request #220 from kekukin/patch-1
Fixed uninstall error for themes.
2017-03-30 01:04:59 +02:00
KekuKin
57732bdff5 Fixed uninstall error for themes.
Was receiving uninstall errors: undefined index: theme
2017-03-30 00:58:11 +02:00
czaks
d85cb47647 report event 2017-03-11 08:34:58 -05:00
vholmes
387ebe9c0c Prevents reports with too many characters 2017-02-15 23:07:50 -02:00
Marcin Łabanowski
f139b34c4a Merge pull request #213 from tlm-2501/patch-1
Show backlinks on OP's as well, and disable the script on Ukko boards, it's broken there anyway.
2017-01-23 20:13:57 +01:00
tlm-2501
e672cf9ba1 Show backlinks on OP's as well, and disable the script on Ukko boards (it's broken there anyway) 2017-01-23 21:15:13 +03:00
Marcin Łabanowski
a989435253 Merge pull request #212 from SHooZ/uk_UA-localization
Add uk_UA localization files
2017-01-22 23:58:32 +01:00
SHooZ
2ca02733ac Add uk_UA localization files 2017-01-22 22:16:56 +00:00
Marcin Łabanowski
90f27d8c2e Merge pull request #211 from tlm-2501/patch-1
Change "Configuration Basics" link to point to the archived tinyboard website
2017-01-18 04:27:38 +01:00
tlm-2501
50d2cfd45e Change "Configuration Basics" link to point to the archived tinyboard website. 2017-01-18 06:21:56 +03:00
Marcin Łabanowski
05cd180102 Merge pull request #209 from int15h/master
New EXIF viewer
2016-12-24 13:45:10 +01:00
int15h
b3071152dc new exif provider 2016-12-24 10:39:30 -02:00
Marcin Łabanowski
8eb8a6e729 Merge pull request #205 from Montrosos/patch-1
Included header.html for better boardlist
2016-12-12 14:38:59 +01:00
Montrosos
1f4de533f0 Included header.html for better boardlist
Simply included the header.html so that the compact boardlist works with it and it's responsive now.
2016-12-12 13:52:42 +01:00
Marcin Łabanowski
4a21c97cb0 Merge pull request #202 from pngcrypt/master
table `pages` fix
2016-11-20 16:44:52 +01:00
pngcrypt
2a669d7113 table pages fix 2016-11-20 03:13:17 +03:00
czaks
65f39b8a07 local-time.js: fixup 2016-10-09 02:11:55 +02:00
czaks
741c29b452 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2016-10-09 02:02:23 +02:00
czaks
c21eeff605 local-time.js: relative time by default 2016-10-09 02:02:13 +02:00
czaks
6049979daf nntpchan install.sql fix 2016-10-09 02:01:23 +02:00
Marcin Łabanowski
1ae5df54dc Merge pull request #200 from seisatsu/patch-2
Fix typo in max_images comment
2016-10-02 00:09:40 +02:00
Michael D. Reiley
372c26491a Fix typo in max_images comment
multi_image.js should be multi-image.js, with a dash, not an underscore.
2016-10-01 15:06:09 -07:00
Marcin Łabanowski
a4b619ae5e Merge pull request #198 from seisatsu/patch-1
Rebuild index when mod deletes a thread.
2016-09-23 09:24:05 +02:00
Michael D. Reiley
8951cb74c8 Rebuild index when mod deletes a thread.
The index does not properly rebuild when a mod deletes a thread, resulting in a ghost thread remaining in the index until the next rebuild. This fix was originally contributed to Uboachan's codebase by Mannosuke.
2016-09-22 23:03:11 -07:00
czaks
3f38a6db97 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2016-08-19 23:15:47 +02:00
czaks
a5e7b3da6f nntpchan: work around php nonsense 2016-08-19 23:15:42 +02:00
Marcin Łabanowski
fc21854770 Merge pull request #196 from majestrate/master
patch for nntpchan stream
2016-08-19 22:08:33 +02:00
Jeff Becker
1c3e6e590a
patch for nntpchan stream 2016-08-19 16:05:50 -04:00
czaks
0b19051891 fix a notice; increase waiting time for dns 2016-08-15 04:13:26 +02:00
czaks
a779b96370 second iteration of nntpchan implementation 2016-08-15 00:56:06 +02:00
czaks
1c24c69999 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2016-08-14 16:24:25 +02:00
czaks
5e335a8564 preliminary inbound nntpchan support 2016-08-14 16:24:17 +02:00
Marcin Łabanowski
a209216656 Merge pull request #195 from ptchan-foss/master
Fixed report syslog message
2016-08-12 19:21:35 +02:00
ptchan-foss
8548a4ff70 Fixed report syslog message 2016-08-12 18:18:54 +01:00
Marcin Łabanowski
7bec8a0a85 Merge pull request #191 from nekomiko482/patch-1
BSD md5 output format compatibility fix
2016-07-08 05:45:18 +02:00
nekomiko482
a55760299c Fixes incompatibility with BSD's md5 output format.
fixes #190
2016-07-07 12:53:40 +03:00
czaks
11cecf8452 Revert "[BUG] Image reject repost board option now also affects YT embeds"
This reverts commit b476b660073adbe827836a7e7860b0fb3a061ff0.
2016-06-21 05:03:44 +02:00
czaks
8f4aa27329 fix file-selector.js dependencies 2016-06-19 02:40:24 +02:00
czaks
fed9065cf1 skip non-image files in recent themes; fixes vichan-devel/vichan#185 2016-06-19 02:23:24 +02:00
czaks
356f46237c fix install.sql after a bad merge 2016-06-19 02:15:49 +02:00
czaks
e230f1472c don`t ocr non-images 2016-06-10 12:41:53 +02:00
fatchan
c9ef21bff9 Better solution to prevent ID wrapping. Also no longer text-selectable. Much cleaner. 2016-06-09 11:23:32 +02:00
Duane Moody
f23d11be60 Prevent poster IDs from wordwrapping
Poster IDs still linebreak between "ID:" and the ID, this corrects that without having to replace the space inbetween with an &nbsp; nonbreaking space.
2016-06-09 11:23:08 +02:00
fatchan
4f3cc7f316 Whoops 2016-06-09 11:22:57 +02:00
fatchan
f27c26907d Remove hardcoded 8chan links in catalog RSS 2016-06-09 11:22:47 +02:00
fatchan
aa0d92a2b4 Force post-hover.js to show OP's on hover. 2016-06-09 11:20:39 +02:00
fatchan
04f42b3802 CSS hover instead of javascript mouseover. Need to use important because the dark/light text determined by IDToRGB is added inline and takes priority over stylesheets. 2016-06-09 11:20:23 +02:00
fatchan
cdd963e79e fix flag spacing 2016-06-09 11:18:34 +02:00
czaks
d2bb4a776f fail gracefully on no thumbnail 2016-06-09 11:15:45 +02:00
czaks
8a46c7a0d5 tesseract OCR support for spamfilters 2016-06-09 11:09:10 +02:00
czaks
36d762514c Merge branch 'master' of github.com:vichan-devel/Tinyboard 2016-06-09 04:51:17 +02:00
czaks
94c91db097 fix news deletion; thanks MrFreeman 2016-06-09 04:51:05 +02:00
Marcin Łabanowski
6a7be4a058 Merge pull request #182 from fatchan/master
Move the 'Go back and rebuild again' to the top of the rebuilt page s…
2016-05-31 16:08:50 +02:00
fatchan
d285a79667 Move the 'Go back and rebuild again' to the top of the rebuilt page so you dont have to scroll 2016-05-31 23:28:55 +10:00
czaks
52fe9bc873 fix sane_strategy for advanced build. should fix the ajax.js problem. 2016-05-15 15:53:30 +02:00
czaks
4fe2da2fcd post-filter & ukko: final solution i think 2016-05-09 13:02:21 +02:00
czaks
018dd48a66 post-filter + ukko fixes 2016-05-09 11:58:46 +02:00
czaks
4479fc7681 thread-watcher and favorites in catalog and ukko 2016-05-09 11:18:35 +02:00
czaks
1cff10fd95 ukko & fix-re-de-su: fix reporting and deleting from ukko actually 2016-05-09 11:08:24 +02:00
czaks
ccc9cff23d ukko: post filters and reporting 2016-05-09 10:59:50 +02:00
czaks
bb9aaad899 i forgot about a queue and a lock implementation 2016-05-08 15:37:49 +02:00
czaks
f24e0f9814 optimize out openboard when we don`t need it. a big performance improvement too 🏎
also, don't call dnsbl for local ip addresses
2016-05-08 14:02:17 +02:00
czaks
12e6aba5d4 (2/2) advanced build. implement a daemon that will build static pages.
implement a queue and a lock. fix notice in bans. and it even works!

the daemon is basic right now, it could work in a mode that it will defer building certain
pages until a certain time.
2016-05-08 13:23:41 +02:00
czaks
e265375475 fixup 2016-05-08 10:59:36 +02:00
czaks
b6f0317bde advanced build (1/2): a small refactor of index generating procedure; generation strategies 2016-05-08 10:54:30 +02:00
czaks
644f227ab3 fix "Undefined variable: pid"; thanks fpdl and MrFreeman 2016-05-08 03:09:20 +02:00
czaks
a5e22f6d63 split route and controller parts from smart build 2016-05-08 02:50:44 +02:00
czaks
deef54fe13 introduce smart_build_helper 2016-05-07 02:16:54 +02:00
czaks
ce9f9eec25 settings dialog refinements: now you can resize it 2016-05-06 17:11:12 +02:00
czaks
3f405b3484 what if IP address contained bad characters? (highly local) 2016-05-06 16:53:28 +02:00
czaks
3571670b98 fix catalog link someone? 2016-05-06 16:51:34 +02:00
czaks
a5bd39dc4a mod dashboard html: link to page editor 2016-05-06 16:49:35 +02:00
Fredrick Brennan
505adffcdc Cyclical threads ♺ 2016-05-06 16:39:20 +02:00
czaks
ab02a42725 maybe we can try to load Parsedown, after all we can silence the error 2016-05-06 16:27:43 +02:00
8chan
d788131202 Allow a board called news to exist 2016-05-06 16:26:17 +02:00
czaks
91c02c3ec4 board pages: add a migration 2016-05-06 16:21:43 +02:00
czaks
d726eaf195 we don't have a htmlpurifier yet ;_; 2016-05-06 16:07:21 +02:00
Fredrick Brennan
95b1e103cb Edit static pages commit 2016-05-06 16:03:55 +02:00
8chan
7911c374e8 Public action logs commit (log.php)
Note: In a previous commit, I began making inc/mod/auth.php more modular with the check_login() function. Including it does NOT check mod login by default anymore like it does on vichan. You have to call check_login(). I've finally included it in inc/functions.php. If you have any custom pages that use inc/mod/auth.php, just including functions.php is enough now.

===================================
Also: backports 351375185e5 (early 404)
2016-05-06 15:44:26 +02:00
8chan
6dd1420f91 Add event to quote backlinks 2016-05-06 15:15:17 +02:00
8chan
ce3ce4f1b6 Fix *0 secure tripcodes caused by accidentally feeding + signs to crypt() 2016-05-06 15:14:55 +02:00
8chan
7831da83fc New event: rebuildpost, allows you to bind events to ?/edit 2016-05-06 15:13:27 +02:00
Fredrick Brennan
b476b66007 [BUG] Image reject repost board option now also affects YT embeds 2016-05-06 15:12:08 +02:00
czaks
2fa37278db boardlist goes before #top 2016-05-06 15:09:25 +02:00
czaks
6e33de568d hide-threads.js: add div.file to fields to hide; thanks fpdl 2016-05-06 15:03:53 +02:00
czaks
8496b021a9 comment out global reports 2016-05-06 14:57:07 +02:00
Fredrick Brennan
65ea7b78c5 Catalog: click to scroll thread 2016-05-06 14:53:17 +02:00
sourcerect
3515fdabe7 Fix tab freeze when inlining
Fixes ctrlcctrlv/infinity#451
2016-05-06 14:49:30 +02:00
czaks
aa98ca337e i think this lump of code deserves a version bump; v5.1.0 here 2016-05-06 14:36:14 +02:00
czaks
126ee42b9d better rules for stripping combined chars, based on 45c0d327619 by @ctrlcctrlv 2016-05-06 14:34:42 +02:00
Forkless
d069a4c9fd Added option for hiding IDs. 2016-05-06 14:32:53 +02:00
czaks
33ef3f9b01 synchronize catalog_link 2016-05-06 14:14:22 +02:00
Bui
33ef1d2123 add active page classes to body; czaks: go to bottom @ thread: fixes 2016-05-06 14:05:16 +02:00
8n-tech
6644ff666a Also improved some CSS and HTML aspects of the thread layout.
Signed-off-by: 8n-tech <8n-tech@users.noreply.github.com>
2016-05-06 13:51:15 +02:00
8chan
7a7574bdca SECURITY / XSS : ?/edit allowed arbitrary HTML to be added by any user thru addition of <tinyboard raw html>1</tinyboard>
This allowed ANY user with ?/edit privilege to also have raw_html regardless of whether they had $config['mod']['rawhtml']

Now, any changes to <tinyboard> markup modifiers via ?/edit are not allowed. They are removed at read time, and before write they are removed again and the ones in the database (which should be clean...) are inserted instead.

Please immediately apply this patch to your instance if you are running any version of 8chan/infinity.
2016-05-06 12:43:25 +02:00
8chan
6da7f4d25a No more country flags in <title> 2016-05-06 12:40:37 +02:00
8chan
ae4eb4d3d9 RSS 2016-05-06 12:40:07 +02:00
8chan
632d0a76d0 Display placeholder if no file in catalog/theme.php; czaks: fix the code a bit 2016-05-06 12:37:00 +02:00
anonfagola
cb97029d0d Update catalog.html
Changed title from being - "Catalog /board/" to "/board/ - Catalog"
2016-05-06 12:27:21 +02:00
czaks
3f29170f1b debrand 8chan; btw. the previous commit was [SECURITY] i think? 2016-05-06 12:23:18 +02:00
8chan
ce62673a2c OpenGraph information in thread pages https://en.wikipedia.org/wiki/Facebook_Platform#Open_Graph_protocol 2016-05-06 12:18:31 +02:00
8chan
aa0d3395b1 Show first 256 chars of body in <title> 2016-05-06 12:17:51 +02:00
8chan
b6f3d44080 Go to bottom link 2016-05-06 12:16:01 +02:00
czaks
293543878a backport parts of 2d6d449bd2d72, in particular html classes 2016-05-06 12:14:28 +02:00
Bui
6c334a3b44 lol spaces 2016-05-06 11:45:52 +02:00
Bui
d46bf4e2f2 add id to thread links 2016-05-06 11:45:37 +02:00
czaks
02c3c28a16 main.js: a bit more sane code 2016-05-05 15:37:50 +02:00
czaks
6991ca270e fix bad merge 2016-05-05 13:53:52 +02:00
8chan
129eb154b3 Merge 2016-05-05 13:45:36 +02:00
Zixaphir
633c223282 Fix trailing comma 2016-05-05 13:43:32 +02:00
Zixaphir
cad8019068 Prevent images from hovering off-page
This entirely affects the "imageHoverFollowCursor" option.
2016-05-05 13:43:17 +02:00
Pashe
5f043d0a29 Have image-hover.js use data-fullimage instead of the API 2016-05-05 13:43:04 +02:00
8chan
913420e040 Image hover backported from 8chan X 2016-05-05 13:42:54 +02:00
czaks
130b32d08b remove image hover, so we can import the whole 8chan history of that file 2016-05-05 13:42:38 +02:00
Fredrick Brennan
2712235f15 Make js/options/favs.js actually usable
I pretty much had to rework this completely to get it into a usable state

Reference ctrlcctrlv/infinity#424
2016-05-05 13:36:26 +02:00
Harry Hackett
6cb3039b71 Create fav.js 2016-05-05 13:35:02 +02:00
Fredrick Brennan
71fde35938 Oops forgot a file 2016-05-05 13:33:14 +02:00
Mark Taiwan
c2e3ff162f Added missing curly brackets in post-filter.js 2016-05-05 13:22:59 +02:00
8chan
7cf3fccda5 Fix menu brokenness if user post deletion disabled 2016-05-05 13:22:36 +02:00
8n-tech
e64b01b690 Javascript ammendments, dio_ on Windows.
Signed-off-by: 8n-tech <8n-tech@users.noreply.github.com>
2016-05-05 13:22:11 +02:00
8chan
6b04b3c671 Fix post deletion 2016-05-05 13:21:09 +02:00
8chan
5f10badee9 Make no-animated-gif.js trigger on new_post 2016-05-05 13:12:10 +02:00
8chan
8412299fa5 Fix hide-threads.js interaction in no-animated-gif.js 2016-05-05 13:11:54 +02:00
Ringstaart
4e635229b4 Replace capital X by clearly superior ASCII ×
There's no reason to use a malformed letter when an ASCII character of a proper cross is available. This is an important issue, and I care about it very much.
2016-05-05 13:08:30 +02:00
8chan
f02226449a Fix own post (You) 2016-05-05 13:06:25 +02:00
Fredrick Brennan
cac428b30c Add some missing i18n tags 2016-05-05 13:03:31 +02:00
8chan
5267098cb8 Make bottom watchlist-toggle work 2016-05-05 13:01:24 +02:00
8chan
fd2e9df30c This script was breaking boards.html 2016-05-05 13:01:00 +02:00
Pashe
01446aad12 thread-watcher.js: fix background and border 2016-05-05 13:00:47 +02:00
Pashe
6f301505e3 thread-watcher.js: change display format 2016-05-05 13:00:33 +02:00
7185
0b1c67574a Fix selector in inline.js
Should make >>>/crossboard/links (and expanding links) work again
2016-05-05 12:59:25 +02:00
Fredrick Brennan
8943bb0bb3 Rewrite report system due to flooding 2016-05-05 12:57:52 +02:00
8chan
95a9b7b72b Completely rewrite fix-report-delete-submit.js, add report/delete to menu 2016-05-05 12:52:17 +02:00
Forkless
4e39262223 Moved the Options tab stuff to be setup after the document is ready. 2016-05-05 12:45:25 +02:00
Forkless
81daf934fb Fix for the js being shitty inside the compiled main.js. 2016-05-05 12:45:07 +02:00
Forkless
f6b4b2ac18 Removed redundant setting.
Bugfix.
2016-05-05 12:44:48 +02:00
Forkless
1663efcf9d Fix for update to comment toolbar (should work now) 2016-05-05 12:43:57 +02:00
Fredrick Brennan
1b0f5fd24c Revert "Comment toolbar update and Thread stats addition" 2016-05-05 12:42:41 +02:00
ForklessAnon
69a6631742 Added option to disable/ignore keybinds. 2016-05-05 12:36:28 +02:00
ForklessAnon
86ddb4ecbb Update formatting toolbar to include user definable settings and customized options. 2016-05-05 12:35:58 +02:00
Markerov
9265ebea43 initial commit 2016-05-05 12:35:45 +02:00
marktaiwan
59ee8a990f post-filter.js: prevent extra space characters
prevent extra spaces in comment caused by joining strings with leading
or trailing space.
2016-05-05 12:33:44 +02:00
8chan
4e27112147 Fix filter for users with emoji in thier names 2016-05-05 12:33:23 +02:00
marktaiwan
a9b29c7232 Bugfix: convert it to string 2016-05-05 12:33:02 +02:00
marktaiwan
513c8f7b68 post-filter.js catalog support
Removes hidden threads from catalog page
Shift click on catalog to hide thread
Improved word matching for simple comment and subject filter.
2016-05-05 12:32:27 +02:00
marktaiwan
dc725641c3 minor options template adjustment 2016-05-05 12:32:00 +02:00
marktaiwan
8f6ea6dd94 post-filter.js restructure
- Changed how filters are stored. Have included code to migrate from
previous version
- Added support for 'subject' and 'comment' in the options panel
- Added regex support in the options panel
2016-05-05 12:31:11 +02:00
marktaiwan
f84d0b9027 Changed 'hide post' button behavior 2016-05-05 12:30:54 +02:00
8chan
b469855126 use onready in post-menu.js 2016-05-05 12:30:18 +02:00
marktaiwan
af91ddf637 Split post menu into own function 2016-05-05 12:29:11 +02:00
8chan
e3dbca5616 Add one click [-]/[+] to post-filter.js 2016-05-05 12:28:52 +02:00
marktaiwan
84bc3b0f7b I forgot how to jQuery 2016-05-05 12:16:55 +02:00
marktaiwan
3e579ee1d4 Bugfix: reset multifile container width
#371
2016-05-05 12:16:17 +02:00
marktaiwan
deefe7225d Bugfix: scroll to thumbnail on multipost close
Indroduced in 7364e85
2016-05-05 12:15:51 +02:00
8chan
5176377045 Fix many features for Internet Explorer 9 and 10
Please don't use "dataset" in scripts anymore, it doesn't work in IE9 or 10. Instead use $.data
2016-05-05 12:15:26 +02:00
marktaiwan
88f6088a42 fix Relative Time and Image Throttler 2016-05-05 12:14:22 +02:00
Markerov
7160cd650e merge relative-time into local-time 2016-05-05 12:12:53 +02:00
Markerov
c3146e1794 image throttler
initial commit
2016-05-05 12:11:12 +02:00
topkek
63491b0b9a Scroll to thumbnail when shrinking an expanded image 2016-05-05 12:10:09 +02:00
Markerov
fd2b41c1f0 Fix bug with inline expansion with Unanimate Gif
Issue #273
2016-05-05 12:09:55 +02:00
Markerov
bc2257be08 scroll to thumb
scroll up to image if its top is out of view when shrunk.
Requires jQuery
2016-05-05 12:09:41 +02:00
Markerov
4767a63178 renamed 'this.childNodes[0]' to thumb 2016-05-05 12:09:10 +02:00
8chan
99ee2e36ba Don't expand webm or YouTube videos on js/expand-all-images.js 2016-05-05 12:06:27 +02:00
Markerov
a723ff8e66 Display inline image when it starts loading,
Rewrote inline-expanding.js to display full image as soon as it starts
loading.
Modified expand-all-images.js to work with the new change
Moved max-width to style.css
2016-05-05 12:05:45 +02:00
marktaiwan
26130c43ea fix menu UI for Firefox 2016-05-05 12:03:24 +02:00
marktaiwan
c8eaebce9a reset thread timer on new filter 2016-05-05 12:03:05 +02:00
marktaiwan
709a248d10 Clear empty thread/board from filter list 2016-05-05 12:02:50 +02:00
marktaiwan
2808b1b8b2 post-filter
Adds a dropdown menu to each post that allows for filtering by:
- post
- post and all replies to it
- poster ID
- poster ID and all replies to it
- name
- tripcode

In the options panel, adds a new tab for adding/removing name and
tripcode filters.
2016-05-05 12:02:34 +02:00
8chan
dd27026618 Show stickies at top of catalog 2016-05-05 12:01:16 +02:00
8chan
e8b530a783 Shift-click to hide threads in catalog 2016-05-05 12:00:21 +02:00
8chan
01207dfcbb Catalog script fix for hiding threads with short IDs 2016-05-05 11:59:59 +02:00
8chan
b056124e49 Catalog: don't show hidden threads 2016-05-05 11:59:16 +02:00
8chan
4f96263e3b Upgrade jQuery mixitup, preserve settings, no animations 2016-05-05 11:59:00 +02:00
8chan
e2016340e1 Fix expand-too-long error with new <p> markup 2016-05-05 11:56:41 +02:00
czaks
cd01191072 those parts are extraneous 2016-05-05 11:45:29 +02:00
8chan
3eb755ee7e Move login check in inc/mod/auth.php to a function
This allows pages like create.php to not include inc/mod/pages.php while still being able to use the mod auth functions (like generating salts and passwords)
2016-05-05 11:40:52 +02:00
8chan Admin
93f748e6a8 Security: capitalization of mods username is significant 2016-05-05 11:39:12 +02:00
czaks
d310abc95c Merge branch 'master' of github.com:vichan-devel/vichan 2016-05-05 10:54:09 +02:00
czaks
186ad5ca86 bsd fixup 2016-05-05 10:53:44 +02:00
czaks
abe4bdd6ae fixup 2016-05-05 10:52:58 +02:00
czaks
19b70663d7 remove magic_quotes check; it`s 2016 after all 2016-05-05 10:29:13 +02:00
czaks
4c827cf105 fix some nonsense 2016-05-05 10:22:34 +02:00
czaks
c4b98e94ce [SECURITY] harden for imagetragick (we aren`t hit by the bug, but we were passing uncommon filetypes, like JPEG2000, directly to imagemagick) 2016-05-05 10:17:14 +02:00
czaks
77176faece enable javascript in mod panel 2016-05-05 09:56:54 +02:00
czaks
38bf3276e4 update copyright years; remove a link to tinyboard (website is dead) 2016-05-05 09:39:23 +02:00
czaks
89fe3db556 ... 2016-05-05 09:25:47 +02:00
czaks
985c113190 ... 2016-05-05 09:18:36 +02:00
czaks
8dac72e924 update installer 2016-05-05 09:16:09 +02:00
czaks
a42256b296 locale cache: fix a bug when perms are done wrong 2016-05-05 08:43:34 +02:00
czaks
36b78e5f98 fix for editor highlighting 2016-05-05 08:40:13 +02:00
czaks
295f597699 Merge branch 'master' of github.com:vichan-devel/vichan 2016-05-05 08:22:47 +02:00
czaks
dcf5d699bd simplify the md5 execution logic 2016-05-05 08:22:19 +02:00
czaks
9768161327 simplify the code a bit 2016-05-05 07:51:55 +02:00
czaks
c898f97493 Merge branch 'master' of https://github.com/vichan-devel/vichan 2016-05-05 06:45:08 +02:00
czaks
7c3126866c ease the migration process for the previous security patch (by introducing another migration); restore php 5.4 compatibility (introducing a polyfill system) 2016-05-05 06:43:22 +02:00
Marcin Łabanowski
2caad90755 Merge pull request #177 from 27chan/master
Fix default theme and add Font Awesome Icons in recent.html
2016-04-30 04:09:24 +02:00
27chan
199931dc1a Fix default theme and add Font Awesome Icons 2016-04-29 18:00:33 -03:00
27chan
f7a47f1b9e New theme northboard_cb
For circleboard by kotiakrobaatti
2016-04-29 15:40:01 -03:00
Marcin Łabanowski
e0a4b479f9 Merge pull request #176 from 27chan/master
Update Font Awesome
2016-04-28 07:09:38 +02:00
27chan
48726950d9 Update Font Awesome
Update Font Awesome to 4.6.1
2016-04-27 14:25:51 -03:00
czaks
caaf741691 [SECURITY] keep up with modern password hashing standards 2016-04-22 05:35:43 +02:00
czaks
c53f13bf90 Merge branch 'master' of https://github.com/vichan-devel/vichan 2016-02-09 12:37:03 +01:00
Matthieu
028fd3df15 Added: RSS theme 2016-01-26 00:51:39 +01:00
Matthieu
d2de4419bd Added: config option to hide email in post. (prevent emailfag but let the possibility to sage and noko) 2016-01-26 00:50:55 +01:00
czaks
844b262166 update readme; mention php 7.0 compatibility 2015-09-11 13:17:33 +02:00
czaks
6d4e756240 fix a bug for some bad database state. thanks Seisatsu for testing 2015-09-11 12:49:42 +02:00
Marcin Łabanowski
8678716297 Merge pull request #164 from JasonPuglisi/font-awesome-4.4.0
Updated to Font Awesome 4.4.0
2015-09-06 03:26:23 +02:00
Jason Puglisi
15dda118d6 Updated to Font Awesome 4.4.0 2015-09-05 19:35:41 -04:00
Marcin Łabanowski
63e88e2474 Merge pull request #161 from kellerwhy/patch-1
Make mod/recent_posts.html respect $config['dir']['res']
2015-08-11 05:25:20 +02:00
kellerwhy
d4dcfc6321 Make mod/recent_posts.html respect $config['dir']['res']
So certain links don't keep linking to /board/res/postnumber despite any changes to $config['dir']['res'] e.g. changing res/ to thread/
2015-08-10 23:16:23 -04:00
czaks
706feeddff fix cache_config: webms were thumbnailed twice and with the latest addition, they couldn`t resize at all 2015-08-11 04:51:27 +02:00
czaks
f6efdee873 expand-video.js: fix regexp 2015-08-11 03:59:18 +02:00
czaks
77bec71399 expand-video.js: works with .mp4 now as well 2015-08-11 03:55:44 +02:00
czaks
a54488d900 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-08-11 03:47:54 +02:00
czaks
1136cc0e44 reflect in readme, that we support .mp4 files as well now 2015-08-11 03:47:44 +02:00
czaks
ccd00c497c a stricter check for webm processing 2015-08-11 03:46:02 +02:00
Marcin Łabanowski
11d4cb0f4f Merge pull request #155 from 27chan/patch-7
Add extension mp4
2015-08-11 03:44:51 +02:00
Marcin Łabanowski
ea5ad66a19 Merge pull request #154 from 27chan/patch-8
Create image-hover.js
2015-08-11 03:40:17 +02:00
Marcin Łabanowski
b0eb49de82 Merge pull request #160 from 27chan/patch-10
Add extension mp4
2015-08-11 03:39:22 +02:00
Marcin Łabanowski
1b099ce072 Merge pull request #158 from 27chan/patch-4
Add extension mp4
2015-08-11 03:34:00 +02:00
Marcin Łabanowski
ae4cac5200 Merge pull request #156 from 27chan/patch-6
Add extension mp4
2015-08-11 03:33:18 +02:00
27chan
219c1987a9 Add extension mp4 2015-08-10 22:25:09 -03:00
27chan
6140f13d75 Create image-hover.js 2015-08-10 22:20:47 -03:00
27chan
f1cbbbc15a Add extension mp4 2015-08-10 22:15:21 -03:00
27chan
601c8cebc9 Add extension mp4 2015-08-10 22:13:42 -03:00
27chan
e6c1623a42 Add extension mp4 2015-08-10 22:09:26 -03:00
Marcin Łabanowski
7aefa96051 Merge pull request #152 from JasonPuglisi/bottom-button
Added [Return] and [Go to bottom] to thread page above posts
2015-08-09 18:10:43 +02:00
Jason Puglisi
90e4208473 Added [Return] and [Go to bottom] to thread page above posts 2015-08-08 13:45:02 -04:00
Marcin Łabanowski
481f9b1475 Merge pull request #151 from JasonPuglisi/hide-videos
Added ability to hide videos/webms
2015-07-29 01:27:35 +02:00
Jason Puglisi
c97475d487 Added ability to hide videos/webms 2015-07-28 18:45:45 -04:00
czaks
d3d167affb SECURITY: XSS fix for youtube.js/metacafe embed 2015-07-08 16:26:58 +02:00
szalwia
11c7c57873 Fix thumbnail scaling in recent theme
Use decoded JSON values to set thumbnail sizes in the recent theme
2015-06-04 17:18:27 +01:00
Anonke
3f29bdfac9 the poster IDs were showing in API despite being disabled 2015-05-30 20:46:43 +02:00
czaks
d20149b579 gallery view: right bar should be 12%, not 15% 2015-04-25 02:26:42 +02:00
czaks
501484088b gallery-view: i forgot the stylesheet 2015-04-23 09:21:16 +02:00
czaks
099e347e15 gallery-view: preloading images, webm support 2015-04-23 09:20:34 +02:00
czaks
163a4e699c gallery-view: support key events (up/down/left/right) 2015-04-23 08:45:39 +02:00
czaks
2d9214ac63 version check should point at engine.vichan.net and not tinyboard.org actually 2015-04-23 08:18:36 +02:00
czaks
4c1d2f924c fix error while installing themes; thanks xixi 2015-04-23 07:57:52 +02:00
czaks
3f02985380 gallery-view.js: initial commit 2015-04-23 07:41:49 +02:00
czaks
271dcb7a65 fileboard: fix possible XSS (mainly applicable to 8chan) 2015-04-23 03:45:08 +02:00
czaks
b5370fd3e5 fileboard: op tag fix 2015-04-23 02:41:17 +02:00
Marcin Łabanowski
4014682882 fileboard support 2015-04-22 06:06:34 +02:00
czaks
4060bf10ed update copyright years & vichan website 2015-04-12 03:18:51 +02:00
czaks
1b16e97f67 [code] fix regexps 2015-04-12 03:08:40 +02:00
czaks
197d5f236f [code] tag support 2015-04-12 01:14:35 +02:00
czaks
4131a6e563 watch.js: slow down a little bit, let`s see how it works out 2015-04-11 23:12:13 +02:00
czaks
cb700e6a72 live index should refresh every 20s 2015-04-11 23:03:45 +02:00
czaks
00ad1ecf15 smart_build: fix one possible performance problem 2015-04-11 21:41:22 +02:00
czaks
bdda1613a6 thread-stats.js: final vichan fix, should work now 2015-04-10 23:43:07 +02:00
czaks
2d68972dd7 thread-stats style: add margins 2015-04-10 23:21:22 +02:00
czaks
f86be0f44d thread-stats: best viewed inline 2015-04-10 23:17:19 +02:00
czaks
c4569b2ea5 thread-stats.js: code typo :^) 2015-04-10 23:13:52 +02:00
czaks
0d0b2fcd7e thread-stats.js: vichan fixes 2015-04-10 23:11:59 +02:00
8chan
c4fc827332 some style fixes
Conflicts:
	templates/8chan/boards-tags.html
2015-04-10 15:37:06 +02:00
Forkless
4b782d6163 Fix thread stats so post count hover works on the OP's id. 2015-04-10 15:36:34 +02:00
8chan
cf91daee7c No need to display pruned in two places...especially if server times out / errors 2015-04-10 15:36:06 +02:00
Forkless
fdc14c699c Fix color incase page is missed and then found again. 2015-04-10 15:35:38 +02:00
8chan
1aa8f6251d Have to load onready 2015-04-10 15:35:25 +02:00
ForklessAnon
8d45128030 Some code cleanup on thread stats. 2015-04-10 15:34:04 +02:00
ForklessAnon
fae2e33c87 Added script for appending thread statistics to the bottom of a thread. 2015-04-10 15:33:44 +02:00
8chan
f2848f2242 Update GeoIP database 2015-04-10 15:03:35 +02:00
czaks
652018f674 own-board.js: initial release 2015-04-07 20:54:43 +02:00
czaks
0658a2b19a fix banned.php; thanks stigma 2015-04-07 02:29:38 +02:00
czaks
11dfc8bbdc fs cache backend: silence the error 2015-04-06 22:51:02 +02:00
czaks
094f60d34d try_smarter: fix two bugs. 1. uncovered by the second, during a bump only the page the thread was on and first page were rebuild, despite threads rearranging their positions on the remaining pages. happening always. 2. during smart build, the page wasn`t ordered to be rebuilt 2015-04-06 18:59:33 +02:00
czaks
64a0b486f2 smart_build.php: nginx – cache 404 replies for 120s 2015-04-06 18:42:23 +02:00
Marcin Łabanowski
8fcb9195c8 Merge pull request #137 from lewdchan/master
made the define_groups function play nice on hhvm
2015-04-05 20:51:51 +02:00
czaks
c50635c700 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-04-05 20:37:40 +02:00
czaks
9831b582fa groups were not defined 2015-04-05 20:25:57 +02:00
czaks
6fd4eb2add fix a locale issue 2015-04-05 20:23:57 +02:00
czaks
f053450edf cache_config: fix debug notice 2015-04-05 20:04:27 +02:00
czaks
45f11d1d78 indent the file (inc/functions.php) after the latest changes 2015-04-05 19:12:41 +02:00
czaks
aadbf4852f tools/rebuild.php: fix for bans.php not included by default and public_banlist 2015-04-05 18:50:16 +02:00
czaks
dc2928a14d cache_config preliminary release 2015-04-05 18:48:53 +02:00
czaks
b8fe93fd8f update gitignore 2015-04-05 18:46:45 +02:00
czaks
1d28b4be4d cache.php: fs cache 2015-04-05 17:13:55 +02:00
czaks
b78b3db010 uncache themes on settings change 2015-04-05 16:59:04 +02:00
czaks
758cb94e01 optimization: locale caching, so we don`t have to reparse instance-config every single time 2015-04-05 16:52:35 +02:00
czaks
e997357084 add tmp subdirectory (a filesystem used for further optimizations) 2015-04-05 16:45:51 +02:00
czaks
71ef3430fc optimization: get rid of one more sql query related to installed themes 2015-04-05 16:38:16 +02:00
czaks
34eeaccea9 optimization: we don`t need bans.php most of the time and bans.php has big dependencies 2015-04-05 16:31:20 +02:00
czaks
cbbebcd20c optimization: if gettext.so is loaded, we don`t need the fallback implementation 2015-04-05 16:26:32 +02:00
czaks
1f9e36868e ukko: small optimization: move js creation to install time 2015-04-05 16:20:59 +02:00
Jayme Brereton
fa2e6cfa80 made the define_groups function play nice on hhvm 2015-04-05 20:14:58 +09:30
Marcin Łabanowski
97d1f2790c Merge pull request #134 from JasonPuglisi/api-tab-fix
Removed tab at start of api.php to fix ban list and possibly other stuff
2015-04-03 14:05:19 +02:00
Jason Puglisi
8cf28682e7 Removed tab at start of api.php to fix ban list and possibly other stuff 2015-04-03 08:03:15 -04:00
czaks
e273111340 sitemap theme for smart_build 2015-04-03 05:57:39 +02:00
czaks
61d2729a40 themes can use smart_build now 2015-04-02 20:54:28 +02:00
czaks
e1a8c4aa7d smart_build.php: a small fix to catalog handling 2015-04-02 20:53:50 +02:00
czaks
fd0f3195b2 smart_build.php: add a protection for +50; maybe we don`t need to rebuild after all? 2015-04-02 20:43:06 +02:00
czaks
018ec3b605 smart_build.php: additional fixes 2015-04-02 20:35:17 +02:00
czaks
67db118f1e Revert "Revert "smart_build: buildThread" (for a moment, something b0rks)"
This reverts commit b246daa191ed6495ce7a73a369c645599eea610e.
2015-04-02 20:30:57 +02:00
czaks
99706835c2 Revert "Revert "smart_build for buildIndex""
This reverts commit cfb2f55b7a6ae314fa03b516192df34bd9849726.
2015-04-02 20:29:43 +02:00
Marcin Łabanowski
0870acb88e smart_build.php: optimizations, guards, also a functionality to correct slugs 2015-04-02 20:28:48 +02:00
czaks
cfb2f55b7a Revert "smart_build for buildIndex"
This reverts commit 55277ce3835fecf44bb1a0cc1ba0b02d23846848.
2015-04-02 19:36:55 +02:00
czaks
e9e5ceaf90 main.js vs new file uploader 2015-04-01 19:37:06 +02:00
czaks
a19853dbe8 smart_build.php: misc fixes 2015-04-01 18:46:48 +02:00
czaks
b246daa191 Revert "smart_build: buildThread" (for a moment, something b0rks)
This reverts commit f2a74812f0a135370969bcdedea8a8c9c3f96aed.
2015-04-01 18:44:01 +02:00
czaks
f2a74812f0 smart_build: buildThread 2015-04-01 18:43:48 +02:00
czaks
14671e0535 functions.php fix: after_open_board support; so that we may disable smart_build immediately after open_board 2015-04-01 18:13:32 +02:00
czaks
55277ce383 smart_build for buildIndex 2015-04-01 18:11:08 +02:00
czaks
ed07404f08 smart_build.php: initial release 2015-04-01 17:50:59 +02:00
czaks
d4892aca12 fix one of the previous commits: fix api_global 2015-04-01 17:30:06 +02:00
czaks
e4e01e4573 smart build: define configuration variables 2015-04-01 17:16:30 +02:00
czaks
4030c42bb4 add a global_api variable for buildIndex 2015-04-01 17:07:24 +02:00
czaks
deefe8299b unlink a .gz version of a file if it exists 2015-04-01 16:56:17 +02:00
czaks
7fd8c75450 dont rebuild a page, when not needed, even if it doesnt exist 2015-04-01 16:53:28 +02:00
czaks
6cbd51b83c for fastcgi users: rearrange post.php, sort of, so that posts are created faster, and we can leave php to generate themes in the background
same for post deletion
2015-03-31 09:21:16 +02:00
czaks
d94143b6c6 fix wpaint & file-selection interaction 2015-03-31 08:58:54 +02:00
topkek
e6da7b4682 clean up options code 2015-03-31 07:53:33 +02:00
topkek
8de9b68f5f checkbox for tree view
Conflicts:
	js/post-hover.js
2015-03-31 07:53:12 +02:00
topkek
1888e174b3 chrome fix 2015-03-31 07:51:41 +02:00
topkek
d67351534a toggle tree view 2015-03-31 07:51:31 +02:00
topkek
2256604dad add global option for tree view 2015-03-31 07:51:20 +02:00
czaks
960053af75 catalog: fix for embed youtube on https 2015-03-31 07:48:03 +02:00
Markerov
6363d8d247 change to use onready() 2015-03-31 07:42:47 +02:00
Markerov
2f7127a3cb Catalog Search 2015-03-31 07:42:34 +02:00
czaks
a8982ce0a9 f+v.css ... 2015-03-31 07:29:52 +02:00
czaks
de1a9fe568 futaba+vichan.css: do proper styling 2015-03-31 07:27:41 +02:00
czaks
0e805c25d8 file-selector.js: allow file dropping anywhere 2015-03-31 07:20:53 +02:00
czaks
745bdc2b6c password is text nao, fuck you chrome 2015-03-31 07:01:51 +02:00
Anonish
d3d54b8c76 Update quick-reply.js
apparently 600 was still not allowing QR to load on portrait mode. 400 seems to work fine
2015-03-31 06:59:49 +02:00
anonish
c74fc6cefb QR fix for tablet (portrait) mode in laptops
Quick reply will now show up on tablets in portrait mode where width can be < 800px as originally coded (mainly 768x1280 and 800x1280)
2015-03-31 06:59:30 +02:00
czaks
388e87746e small tweaks to stylesheet 2015-03-31 06:55:29 +02:00
czaks
765dea599b trivial fixes to file-selector.js 2015-03-31 06:50:05 +02:00
marktaiwan
6f94a06586 file selector: correct typo, click event target 2015-03-31 06:02:08 +02:00
marktaiwan
e42ffb2768 fix file selector element reference
fix thumbnail image not applying to main form with quick reply open
2015-03-31 06:01:50 +02:00
8chan
419d69b4ee ayylmao @marktaiwan 2015-03-31 06:01:23 +02:00
8chan
f26256f55a Make file selector work, add to config
Conflicts:
	inc/instance-config.php
	templates/post_form.html
2015-03-31 05:59:54 +02:00
marktaiwan
6e84a25f9a Adds keyboard focus to file selector 2015-03-31 05:57:45 +02:00
marktaiwan
4da073b6e8 Keep quick-reply and main form in sync
Use object-url instead of data-url due to shorter length
2015-03-31 05:57:26 +02:00
marktaiwan
0005f11098 initialize file selector soon as it's loaded
Conflicts:
	templates/post_form.html
2015-03-31 05:57:22 +02:00
marktaiwan
3bd7f94861 Fallback for browsers that disables javascript
Conflicts:
	stylesheets/style.css
	templates/post_form.html
2015-03-31 05:54:07 +02:00
marktaiwan
d7f82c58fd Run on index and thread
Clear file queue after upload success

corrected fallback detection
2015-03-31 05:51:28 +02:00
czaks
5a9af83ba6 better slugify support for api 2015-03-31 05:50:52 +02:00
marktaiwan
48cd7438a1 initial commit file-selector.js 2015-03-31 05:50:42 +02:00
8chan
0f1d506586 Change this message again
Conflicts:
	js/ajax.js
2015-03-31 05:48:45 +02:00
8chan
d3cc27ff5c Handle XHR errors better 2015-03-31 05:47:09 +02:00
8chan
4083c92dbe Stop double posting AJAX bug 2015-03-31 05:46:45 +02:00
8chan
61371f77ce rebuild2 - multithreaded rebuild script 2015-03-31 05:38:14 +02:00
czaks
e35d261ff4 enable embed field for api 2015-03-31 05:32:38 +02:00
8chan
4a22ee9245 Extra files and IDs in API
Conflicts:
	inc/api.php
2015-03-31 05:28:08 +02:00
czaks
300e9e7e71 fix some png images being discarded 2015-03-31 05:20:00 +02:00
czaks
8f30b02c97 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-03-30 06:27:05 +02:00
czaks
5d8e023fc4 remove tinyboard special markup from slugs; thanks stigma for reporting 2015-03-30 06:26:53 +02:00
Marcin Łabanowski
cdac85bb2b Merge pull request #133 from JasonPuglisi/horizontal-quick-reply-resize
Made quick-reply box resizable horizontally
2015-03-30 05:24:11 +02:00
Jason Puglisi
25c2a18a71 Made quick-reply box resizable horizontally 2015-03-29 22:31:38 -04:00
Marcin Łabanowski
8eb3d709f7 Merge pull request #129 from JasonPuglisi/active-content-fix
Fixed and re-enabled active content stat for recent theme
2015-03-28 05:22:02 +01:00
czaks
10f93d0d43 implement a protection against transparent proxies 2015-03-24 05:19:25 +01:00
czaks
9fa320838b wpaint has new dependencies – important! 2015-03-23 01:09:16 +01:00
czaks
11c020be9b Merge branch 'master' of github.com:vichan-devel/Tinyboard
Conflicts:
	templates/post/image_identification.html
2015-03-23 00:35:48 +01:00
czaks
81afc17b67 image identification: url encode 2015-03-23 00:35:13 +01:00
czaks
158371dc64 switch to hotwheels' wPaint branch 2015-03-23 00:33:19 +01:00
Jason Puglisi
034b288a13 Fixed to work with multiple images 2015-03-20 09:47:40 -04:00
Jason Puglisi
1283e51ca5 Fixed and re-enabled active content stat for recent theme 2015-03-19 21:49:57 -04:00
Marcin Łabanowski
d4d5f59451 Merge pull request #128 from JasonPuglisi/img-id-space-fix
Added space after Google image search link
2015-03-20 00:50:17 +01:00
Jason Puglisi
d6e91ec62f Added space after Google image search link 2015-03-19 19:35:28 -04:00
czaks
d863bf09fa update readme 2015-03-12 17:13:04 +01:00
czaks
3851087dce slug size should be configurable 2015-03-12 00:03:22 +01:00
czaks
a16538e82e Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-03-12 00:01:20 +01:00
Marcin Łabanowski
10a8219965 enable a basic cache by default; notify me if it breaks your chan 2015-03-12 00:00:59 +01:00
Marcin Łabanowski
0f533aaded Merge pull request #127 from JasonPuglisi/settings-space-fixes
Removed extra space for some options
2015-03-11 22:36:50 +01:00
Jason Puglisi
e7d3097e5a Removed extra space for some options 2015-03-11 16:35:49 -04:00
czaks
dbaaa0c40a watch.js & slugify fix 2015-03-10 14:52:44 +01:00
czaks
bf1b6103cf Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-03-10 14:22:47 +01:00
czaks
6c4d3941fa api fix 2015-03-10 14:22:29 +01:00
czaks
4bf525599e ... 2015-03-10 14:19:36 +01:00
czaks
a2544bc596 ... (cites) 2015-03-10 14:16:27 +01:00
czaks
50b80e9e24 ... (slug api) 2015-03-10 14:06:44 +01:00
czaks
9f34d334d3 .. 2015-03-10 13:52:31 +01:00
czaks
2f7aeec531 ... 2015-03-10 13:48:33 +01:00
czaks
58b60f0aa4 ... 2015-03-10 13:46:34 +01:00
czaks
7623de9e2f ... (cache) 2015-03-10 13:42:10 +01:00
czaks
4aa1d387f8 ... 2015-03-10 13:34:02 +01:00
czaks
e999955d08 ... 2015-03-10 13:28:55 +01:00
czaks
7d92a05bd8 ... 2015-03-10 13:23:40 +01:00
czaks
d690567b44 ... (minor fix for locales) 2015-03-10 13:16:16 +01:00
czaks
fe66c51a19 ... (minor fix for locales) 2015-03-10 13:13:18 +01:00
czaks
0062125f5c ... 2015-03-10 13:09:53 +01:00
czaks
fe7e9c5103 ... 2015-03-10 13:03:47 +01:00
czaks
429c9f890f ... 2015-03-10 13:02:38 +01:00
czaks
f4bba2e9ed ... 2015-03-10 12:57:06 +01:00
czaks
bdb6001f3f support for slugified links; may introduce a few bugs 2015-03-10 12:48:59 +01:00
czaks
eb245c2970 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-02-27 21:24:57 +01:00
czaks
bffe03e651 rearrange config processing a bit 2015-02-27 21:16:03 +01:00
Marcin Łabanowski
f51e72c63d Merge pull request #123 from JasonPuglisi/master
Fixed not being able to post without 'mod' post variable set
2015-02-27 16:50:41 +01:00
Jason Puglisi
6d28f9c98e Fixed error that would prevent posting without ['mod'] 2015-02-26 22:51:45 -05:00
czaks
a93f168c79 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2015-02-26 21:44:52 +01:00
czaks
0ab8890b67 tools/rebuild: show currently rebuilded themes 2015-02-26 21:44:39 +01:00
Marcin Łabanowski
30d2f3adc3 Merge pull request #117 from benhc123/patch-1
Updated license date
2015-02-26 21:18:41 +01:00
Marcin Łabanowski
56b29f799a Merge pull request #121 from yeltsew7/master
Add in board locking
2015-02-26 21:18:11 +01:00
yeltsew7
aa0d606651 Add in E Z board locking 2015-02-15 21:23:26 -05:00
Wesley
2d396c4eb8 Add E Z board locking feature 2015-02-15 21:16:36 -05:00
8chan
a550c63f9c SECURITY / XSS : Stop XSS in post subjects displayed in catalog
git blame says czaks forgot an |e in catalog.html, this means that anyone posting a new thread with HTML in the subject field or name field can arbitrarily insert it into the page.

Conflicts:
	templates/themes/catalog/catalog.html
2015-01-23 10:40:08 +00:00
Ben Holden-Crowther
014f9734ac Updated license date
Updated license date to 2015 for new year.
2015-01-01 10:48:28 +00:00
czaks
f4422e597b fix a related bug 2014-10-24 13:43:15 +02:00
czaks
bd6e5da096 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-10-24 13:24:39 +02:00
czaks
daad519b85 config[php_md5] feature 2014-10-24 13:24:33 +02:00
Marcin Łabanowski
fe196be399 install.php: php 5.4 suggestion, remove imagick suggestion
imagick support is unsupported and deprecated
2014-10-24 01:44:09 +02:00
Marcin Łabanowski
14e9697c6f requirements: php 5.3 -> php 5.4 2014-10-24 01:40:30 +02:00
czaks
f16c14640e hide-threads.js: hide youtube videos and other iframe embeds as well; fixes ctrlcctrlv#193 2014-10-20 14:28:22 +02:00
czaks
4220b259e6 show-own-posts.js: remove a debugging expression 2014-10-18 22:44:38 +02:00
czaks
b55ebcd0ef custom alert: now alert will be able to display custom HTML 2014-10-18 22:43:35 +02:00
czaks
638931b02d show-own-posts.js: fix a bug 2014-10-18 19:35:41 +02:00
czaks
e3652ef980 shown-own-posts.js: documentation fix 2014-10-18 16:50:21 +02:00
czaks
67988221b4 show-own-posts.js initial commit 2014-10-18 16:36:04 +02:00
czaks
f9308ff28d fix options.js textareas 2014-10-18 15:45:01 +02:00
czaks
6fc4c02c4e ajax.js: add ajax_after_post event 2014-10-18 15:31:48 +02:00
czaks
31097b89d1 overcome a transifex bug with translation of one string 2014-10-18 13:59:17 +02:00
czaks
24548e377c update locales 2014-10-18 13:54:27 +02:00
clsr
49079e57fb Fix expanded tabs 2014-10-18 13:43:25 +02:00
clsr
d266908ca9 Fix API: Swap image width/height, make replies an integer, fix original filename 2014-10-18 13:43:25 +02:00
8chan
6052ed8d3d SECURITY: imagemagick/graphicsmagick was ignoring all errors
So, in a much older patch I had a problem where an incorrect RGB
profile would make image uploads fail. I fixed this by using strpos
against the error message...but didn't check the return value
correctly.

That means that any error from gm/im was ignored. This caused people
to upload too large images and flood /b/ with 1 x 10000 pixel images

My fault, patched now. Sorry about that.

Conflicts:
	inc/image.php
2014-10-12 10:23:03 +02:00
8chan
b2cbb70da3 Khorne in #8chan on irc.rizon.net contributed this thread watcher.
Can't properly attribute the code to him because he doesn't want it
connected to his Github account for some reason.

Conflicts:
	inc/instance-config.php
2014-10-11 20:41:40 +02:00
8chan
f3e2131f06 Actually fix new_post event inline.js 2014-10-11 20:39:25 +02:00
8chan
1506bcc834 Make inline work on new_post event 2014-10-11 20:38:02 +02:00
8chan
803c76a800 .x.x less confusing...will change to less_ip eventually 2014-10-11 20:37:58 +02:00
czaks
5d1b426fa3 fix bans.php on removing a ban by a semi-privileged mod 2014-10-11 20:13:05 +02:00
czaks
3a552e5b76 hopefully fix locales 2014-10-09 04:09:30 +02:00
czaks
dfd05e88f9 possible fix of themes` interactions 2014-10-09 03:57:18 +02:00
czaks
74a40b72ed ban-list.js: vstaff 2014-10-09 02:03:35 +02:00
czaks
ef3bb46876 bans.php: surpress error 2014-10-09 02:00:31 +02:00
czaks
948695e73c lel, this one will do 2014-10-09 01:49:29 +02:00
czaks
7719ad3e81 minor bugfix @ banlist 2014-10-09 01:26:34 +02:00
czaks
ccd871c195 missed ban-list.css from banlist commit 2014-10-09 01:01:41 +02:00
czaks
ab96e30d89 infinite scroll implementation 2014-10-09 00:58:30 +02:00
czaks
9b3fa77719 new banlist implementation; also includes a public banlist 2014-10-08 23:23:59 +02:00
czaks
906764a62f bundle longtable library @ https://github.com/czaks/longtable 2014-10-08 23:19:03 +02:00
czaks
ca42984ddc i18n auto-reload.js 2014-10-07 05:40:37 +02:00
8chan
9768bb6726 fuck 2014-10-07 04:41:41 +02:00
8chan
582c77a935 Fix name and order 2014-10-07 04:41:41 +02:00
8chan
b7e9007ad4 This makes the options appear at the bottom for some reason 2014-10-07 04:41:41 +02:00
8chan
894faf989c User can disable backlinks if they want to, off by default 2014-10-07 04:41:41 +02:00
8chan
1f28316fca Make inline.js work in mod panel
Conflicts:
	inc/instance-config.php
2014-10-07 04:41:05 +02:00
8chan
c4dc3f4d47 Fix spoiler image not working 2014-10-07 04:33:57 +02:00
8chan
f294af104b Reset to global locale before openBoard 2014-10-07 04:32:10 +02:00
James Campos
fee03312d7 optional backlink hiding 2014-10-07 03:27:36 +02:00
James Campos
0b8728d7ce add loading stub 2014-10-07 03:27:36 +02:00
James Campos
f1b89a5302 optional 2014-10-07 03:27:36 +02:00
James Campos
1e04f29485 extract caching 2014-10-07 03:27:36 +02:00
James Campos
daa30a12de better op selector, don't attach to links 2014-10-07 03:27:36 +02:00
James Campos
262f525e75 fix 2014-10-07 03:27:36 +02:00
James Campos
702e20753a clearfix 2014-10-07 03:27:36 +02:00
James Campos
9dce04ebc8 remove inlined posts for new inlined posts 2014-10-07 03:27:35 +02:00
James Campos
2f85073d28 fix front page backlink 2014-10-07 03:27:35 +02:00
James Campos
3ce156a0d0 rename 2014-10-07 03:27:35 +02:00
James Campos
3c98319e52 front page fixes 2014-10-07 03:27:35 +02:00
James Campos
9ea5ff610e bypass (OP) text 2014-10-07 03:27:35 +02:00
James Campos
b1a5911673 fix when quote is last element 2014-10-07 03:27:35 +02:00
James Campos
aea23e99b6 less invasive css fix 2014-10-07 03:27:35 +02:00
James Campos
bb193e93e2 fix for image posts 2014-10-07 03:27:34 +02:00
James Campos
8d91efc560 grab the whole post 2014-10-07 03:27:34 +02:00
James Campos
26e343d02a fix 2014-10-07 03:27:34 +02:00
James Campos
ee4716b048 work for backlinks 2014-10-07 03:27:34 +02:00
James Campos
91ab8eeae6 disable highlightReply 2014-10-07 03:27:34 +02:00
James Campos
970ff0d619 this is how you cache 2014-10-07 03:27:34 +02:00
James Campos
51a74bbd73 fix selector 2014-10-07 03:27:34 +02:00
James Campos
67d3449998 fix cross-thread inlining 2014-10-07 03:27:33 +02:00
James Campos
274ac0965a get op from input value 2014-10-07 03:27:33 +02:00
James Campos
3de119e417 maybe support cross thread inlining 2014-10-07 03:27:33 +02:00
James Campos
cb92ee0483 inline 2014-10-07 03:27:33 +02:00
8chan
93b30d6829 class around poster IDs 2014-10-07 00:19:15 +02:00
wopot
c7351dff09 4 times "elseif" is not the way
and precalc. value sometimes help if well commentent
2014-10-07 00:16:02 +02:00
Bui
cb9b4db73d do security checks *after* checking captcha 2014-10-07 00:15:45 +02:00
Bui
aba8d27ace wasn't aware of DNS function 2014-10-05 23:20:06 +02:00
Bui
1e95e58811 don't break if dns_system is true 2014-10-05 23:20:06 +02:00
Bui
8b9932218f add forward-confirmed reverse DNS 2014-10-05 23:20:06 +02:00
czaks
6804a2ede0 remove default margin for table elements; fixes vichan-devel#95 2014-10-05 22:16:36 +02:00
Marcin Łabanowski
2b1a1dffa4 Merge pull request #104 from kaernyk/master
Fix post width & codeblocks
2014-10-05 22:11:44 +02:00
kaernyk
944c3b6c28 Fix post width & codeblocks
I noticed that some url's were causing the posts to stretch over the
maximum device with.

  The code blocks were exhibiting similar behavior as well, and have
been adjusted to display well on all themes.

  I still need to fix the post form for handhelds, though it is not
as annoying as the other things fixed
2014-10-05 15:40:42 -04:00
czaks
8518164352 sync locales with transifex 2014-10-05 18:38:25 +02:00
czaks
606b39450d better synchronize the javascripts with 8chan 2014-10-05 18:30:47 +02:00
czaks
1964279436 Merge branch 'master' of github.com:vichan-devel/Tinyboard
Conflicts:
	stylesheets/style.css
2014-10-05 18:01:01 +02:00
Marcin Łabanowski
3f652ce9ad Merge pull request #93 from kaernyk/master
Improve Catalog display & thread title handling
2014-10-05 17:57:42 +02:00
Marcin Łabanowski
97a25dad03 Merge pull request #102 from cable6-dev/bugfix-genwebmerror
[bugfix]$config['error']['genwebmerror'] wasn't set in config.php
2014-10-05 17:56:46 +02:00
Marcin Łabanowski
d01d892896 Merge pull request #100 from cable6-dev/feature-hide-sage
Added an option to hide sages
2014-10-05 17:53:32 +02:00
Marcin Łabanowski
42868c672a Merge pull request #103 from cable6-dev/bug-fix-check_spoiler_size
Check spoiler_image size before ussuming it is 128×128px
2014-10-05 17:53:08 +02:00
czaks
1e1a73c4b4 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-10-05 17:52:30 +02:00
Bui
5f521adfd5 fix hide link on images fetched with ajax 2014-10-05 17:49:31 +02:00
ScriptKi77y
7d5899d3a7 Quick fix to remove lag..
Executing a function to make a get request while simultaneously triggering a scroll event within the executed scroll event is probably not the best idea.

This still needs work, there should probably be something else used to check for updates, such as an event where page has focus or something else that doesn't get called so many times, preferably something that reduces the timer instead.

This is just a quick fix to stop all the lag on threads when scrolling near the bottom.
2014-10-05 17:49:31 +02:00
Bui
62b7e02050 give OPs IDs 2014-10-05 17:49:31 +02:00
Bui
1edaea309b quote selected text on cite 2014-10-05 17:49:31 +02:00
ScriptKi77y
2ece97d685 Scroll hook thread polling adjusttment.
Fixed an issue with the scroll hook thread polling.
Users scrolling near the bottom of the page are making upwards of 7-10 requests a second to the site.

Added a small timer using the "poll_interval_mindelay" value to prevent unnecessary polling, one is enough during this minimum time delay.
2014-10-05 17:49:30 +02:00
czaks
86eed0b349 add stylesheet choice to catalog theme 2014-10-05 17:49:27 +02:00
Bui
7aa2976524 wrap updater in ID span 2014-10-05 17:48:51 +02:00
topkek
c4fd370d3f Update settings.js 2014-10-05 17:48:51 +02:00
7185
b34f9c31f9 Poster ID readability
Conflicts:
	js/id_colors.js
2014-10-05 17:48:43 +02:00
Bui
6133386b82 change ID text colour on hover 2014-10-05 17:48:07 +02:00
Bui
22f4543e6f remove vertical padding on coloured IDs 2014-10-05 17:48:07 +02:00
topkek
71491bc9e9 Update auto-reload.js 2014-10-05 17:48:07 +02:00
topkek
dd99b22f06 Update settings.js 2014-10-05 17:48:07 +02:00
topkek
3918386aab Update settings.js 2014-10-05 17:48:07 +02:00
topkek
9a096f5888 Update auto-reload.js 2014-10-05 17:48:07 +02:00
8chan
6cfb1eb656 Merge bui-boardlist-css, close ctrlcctrlv/8chan#104 2014-10-05 17:48:07 +02:00
8chan
8bfd5e1bcd this>el 2014-10-05 17:48:07 +02:00
8chan
f8178dcbe4 Color IDs on new posts received via AJAX 2014-10-05 17:48:07 +02:00
8chan
035f8437ab Call on ready, dont pollute window namespace with vars 2014-10-05 17:48:07 +02:00
8chan
c3ba4cc7ef Remove prototype pollution, call on ready 2014-10-05 17:48:07 +02:00
anonfagola
cbe12019c4 Added pointer cursor to ids, to show clickability
Conflicts:
	stylesheets/style.css
2014-10-05 17:48:00 +02:00
anonfagola
01ce31a516 Added id_colors.js 2014-10-05 17:46:58 +02:00
anonfagola
b419c85f8c Forgot .js extension 2014-10-05 17:46:57 +02:00
anonfagola
fda530953b Create id_highlighter 2014-10-05 17:46:10 +02:00
kaf
3c2529e157 [bugfix]$config['error']['genwebmerror'] wasn't set in config.php 2014-10-05 15:35:52 +00:00
Marcin Łabanowski
6b08e09008 Merge pull request #97 from cable6-dev/bugfix-ban_appeals
[bugfix]ban appeals (was also present in tinyboard)
2014-10-05 17:34:10 +02:00
kaf
296e4fd5fa Added an option to hide sages 2014-10-05 15:29:37 +00:00
kaf
fe60590d19 Check spoiler_image size before ussuming it is 128×128px 2014-10-05 15:26:28 +00:00
kaf
9cee5f6c61 [bugfix]ban appeals (was also present in tinyboard) 2014-10-05 12:53:02 +00:00
kaernyk
e10f0885af Change body font back to 10pt 2014-09-28 05:19:00 -04:00
kaernyk
f4455cf64d Remove duplicate attributes 2014-09-28 04:54:45 -04:00
kaernyk
0fa1c58249 Improve thread/title handling on small screens 2014-09-28 04:37:33 -04:00
kaernyk
f6e827ca75 Merge branch 'master' of https://github.com/kaernyk/vichan
Conflicts:
	stylesheets/style.css
2014-09-28 04:30:22 -04:00
kaernyk
78cf4a8b56 Improve catalog thread dimensions on tiny devices 2014-09-28 04:28:59 -04:00
kaernyk
197e4d4bfc Merge pull request #1 from vichan-devel/master
Merge changes in upstream
2014-09-28 04:27:57 -04:00
8chan
cb7b7d070c threadscroll was in template for no reason 2014-09-27 11:37:50 +02:00
czaks
ef53af04ec fix a recently added md5 api field 2014-09-27 11:31:30 +02:00
czaks
629b1c92a6 fix a recently introduced quick-reply max-width issue 2014-09-27 11:26:30 +02:00
czaks
f2e101f30d fix multi-image.js when quick-reply isn`t loaded 2014-09-27 11:22:28 +02:00
czaks
6c139caf3c style.css: setting default font size is imo a bit invasive 2014-09-27 11:16:16 +02:00
czaks
dda7462013 catalog link not always working; fix ctrlcctrlv#88 2014-09-27 11:13:04 +02:00
8chan
6fd3b64c67 Disallow multiple Shrink all images appearing
fixes vichan-devel#91
2014-09-27 10:55:14 +02:00
8chan
56f3d89774 Fix multi image from quick reply
Conflicts:
	js/multi-image.js
2014-09-27 10:52:24 +02:00
anonfagola
d9f20c290d Updated threadscroll.js with bettter compatibility 2014-09-27 10:48:36 +02:00
Marcin Łabanowski
9596b6ace3 Merge pull request #92 from kaernyk/master
[WIP] Improvements to mobile display on boards/catalog
2014-09-27 10:47:21 +02:00
kaernyk
a3c03932c3 Fix mobile scaling/padding 2014-09-27 01:38:25 -04:00
kaernyk
c115ebc7e0 Improved image handling in catalog for various screen sizes 2014-09-26 22:54:01 -04:00
kaernyk
2e46875125 Improvements to mobile display on boards/catalog 2014-09-26 14:38:08 -04:00
adonisk
d98eb528a5 v8ch.css 2014-09-26 19:08:46 +02:00
czaks
ef1ceb4f3b fix catalog margins 2014-09-26 14:35:25 +02:00
kaernyk
b223b2b2f8 Remove erroneous data and fix indentation
Conflicts:
	stylesheets/style.css
2014-09-26 14:29:37 +02:00
kaernyk
b1ea8b18d0 Improve image handling in catalog to improve consistency
Conflicts:
	stylesheets/style.css
2014-09-26 14:28:20 +02:00
czaks
b4b99cd936 Merge branch 'master' of github.com:vichan-devel/Tinyboard
Conflicts:
	stylesheets/style.css
2014-09-26 14:08:40 +02:00
kaernyk
359c295eca Correct thread:hover highlighting 2014-09-26 14:07:40 +02:00
kaernyk
153622c068 Corrected changes improperly set in catalog.css
Conflicts:
	stylesheets/style.css
2014-09-26 14:07:31 +02:00
czaks
bfb85fc2b1 catalog.css is no longer used 2014-09-26 13:35:56 +02:00
czaks
76439cbdd9 we don`t use tooltipster anymore, do we? 2014-09-26 13:35:07 +02:00
hatstand0
d27cddaacc Add file hash to API
The API currently lacks the Base64 encoded file hash 4chan's API provides, which assists in file de-duplication by archive software.
2014-09-26 13:28:04 +02:00
hatstand0
7ea5b129e6 Fix thumbnail width/height in API
The API currently has the thumbnail widths and heights switched around
2014-09-26 13:27:49 +02:00
Nebs
ab2a83d194 Fixes catalog href on a potential /res/ board 2014-09-26 13:10:21 +02:00
Nebs
b7592c3eec Fixed unanimating gifs in the catalog 2014-09-26 13:10:14 +02:00
czaks
afbe945d83 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-09-26 13:07:52 +02:00
kaernyk
e5ce012a09 Adjust theme via catalog.css & style.css
Changes to catalog.css:

  - Forced all threads to a height of 300px and reduced padding to
    improve consistency. I think it improves the readability quite a bit
    but I may be alone in thinking this way.
  -

Changes to style.css:

  - Removed additional padding to allow new catalog spacing

Conflicts:
	stylesheets/style.css
2014-09-26 13:05:04 +02:00
kaernyk
b888500133 Corrected thread padding via style.css
Conflicts:
	stylesheets/style.css
2014-09-26 13:04:01 +02:00
czaks
ba515c5f05 post-hover.js: show a popup preview if a reply is only partially on screen; fixes ctrlcctrlv#84 2014-09-26 12:56:05 +02:00
Zealotux
f71cdcaa81 Update style.css
Added "cursor" to "options_tab_icon" according to https://github.com/ctrlcctrlv/8chan/issues/80
2014-09-26 12:47:07 +02:00
8chan
e81d016ffa Attempt to fix scroll to anchor issue 2014-09-25 06:56:24 +02:00
czaks
dbaeb395ac auto-reload.js: it`s actually setTimeout, not setInterval, right? 2014-09-25 06:32:53 +02:00
czaks
ed5272f17d auto-reload.js: don`t scroll up 2014-09-25 06:31:40 +02:00
8chan
5d8d20fcc5 Add timer to auto reload js
Conflicts:
	js/auto-reload.js
2014-09-25 06:30:55 +02:00
TheHowl
7cac637c36 oh hey look I just fixed #8 search.php
It was just a typo, an horrible typo.
2014-09-25 06:24:36 +02:00
czaks
40409f8717 fix reference to oekaki in readme; fixes vichan-devel#89 2014-09-25 06:13:45 +02:00
czaks
3b2f448102 restore compatibility with php < 5.5; fixes vichan-devel#86 2014-09-24 12:26:15 +02:00
czaks
b2d574fec3 Update README.md; fixes ctrlcctrlv#38 ;) 2014-09-24 08:45:14 +02:00
anonfagola
b9886dc474 Update threadscroll.js
Made compatible for use with additional_javascripts.
2014-09-24 04:47:40 +02:00
anonfagola
712e7f6c57 Update threadscroll.js
Made cleaner.
2014-09-24 04:47:40 +02:00
anonfagola
f5d121af10 Update threadscroll.js
Fixed a line left from debug, and added comments.
2014-09-24 04:47:40 +02:00
anonfagola
45dd9e637f Added scrolling threads with up and down keys
For 8chan X. Redone so it's in js folder.
@KillerWhale321
2014-09-24 04:47:40 +02:00
anonfagola
2a823ae786 Create threadscroll.js 2014-09-24 04:47:40 +02:00
czaks
ba49bc6c37 update locales 2014-09-24 03:48:46 +02:00
czaks
fd9196f036 tools/stats.php: restore php 5.3 compatibility; fixes vichan-devel#85 2014-09-24 03:43:23 +02:00
czaks
a25e5f7839 additional measurements for catalog, so it does not throw errors; should fix vichan-devel#84 2014-09-24 03:21:35 +02:00
czaks
92183e8e39 add portuguese (portugal) translation by Chorizo 2014-09-21 08:37:16 +02:00
czaks
b3a2c62cbd tag for 4.9.92 2014-09-21 05:58:49 +02:00
dubcheck
c2f612bac9 'no comment' in Recent theme 2014-09-21 05:51:17 +02:00
czaks
a1f26e8fd1 update locales 2014-09-21 04:52:18 +02:00
czaks
d233344534 style options dialog 2014-09-21 04:34:36 +02:00
czaks
7ec728ffb0 add a go to top link thread view; fixes #82 2014-09-21 02:52:20 +02:00
czaks
56ed7fd8cd User JS and User CSS functionality. fixes #29 2014-09-21 02:29:33 +02:00
czaks
5f7e62142c SECURITY: prevent a DoS attack by disabling HTTP access to tools/ scripts. 2014-09-21 00:56:00 +02:00
czaks
c5c356e077 css/options.js: style option dialog in yotsuba/dark/dark roach and roach styles 2014-09-20 22:48:21 +02:00
czaks
e7eafa135f favorites.js: add info about a possible conflict 2014-09-20 22:24:33 +02:00
czaks
7e8bf0ec49 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-09-20 22:14:04 +02:00
czaks
f5820d2aae move a few options to a general tab in options panel 2014-09-20 22:10:44 +02:00
Fredrick Brennan
7288f1dec7 Fix last commit 2014-09-20 16:49:32 +00:00
Fredrick Brennan
23c73ca839 Allow the user to decide whether or not he wants to display his country 2014-09-20 16:35:28 +00:00
Fredrick Brennan
1ce9fb8174 Allow users to choose their favorite boards for sites w/too many to put in bar 2014-09-20 16:35:19 +00:00
Fredrick Brennan
9070b061ee Bug fix: users were banned from /0/ if they had a ban anywhere else
Conflicts:
	inc/bans.php
2014-09-20 15:39:47 +00:00
czaks
ea3c571d6c Merge branch 'catalog-spoiler-fix' of https://github.com/marlencrabapple/vichan 2014-09-20 06:44:03 +02:00
czaks
3919ad911c fix previous commit 2014-09-20 06:43:02 +02:00
czaks
ac888a769d add a very small image size for catalog 2014-09-20 06:40:43 +02:00
czaks
56e55d157a remove a special containerchan stylesheet; it added some extra space for webms 2014-09-20 06:36:39 +02:00
czaks
f7a015e7fe add user-options dialog functionality; port webm-settings to it; make a basic general settings applet; make it work on mobiles 2014-09-20 06:19:34 +02:00
czaks
ceaaae824a fix an issue with watch.js on android chrome 2014-09-20 06:08:14 +02:00
Marcin Łabanowski
7d91fffdd8 Merge pull request #81 from marlencrabapple/recent-spoiler-fix
Fixed spoiler thumbnails not showing up in the recent theme.
2014-09-18 06:20:36 +02:00
marlencrabapple
14cd12ff2a Fixed spoiler images in the catalog theme. 2014-09-17 16:15:18 -07:00
marlencrabapple
40787db177 Fixed spoiler thumbnails not showing up in the recent theme 2014-09-17 15:55:16 -07:00
Marcin Łabanowski
4da5f4ec90 Merge pull request #79 from marlencrabapple/master
FFmpeg support for WebM uploads
2014-09-17 20:50:21 +02:00
Marcin Łabanowski
c369377c84 Merge pull request #80 from marlencrabapple/catalog-fixes
A few catalog theme fixes
2014-09-17 20:50:04 +02:00
Ian Bradley
cff2af99d5 Fixed blank catalog image count when zero image replies and threads with deleted files from being excluded 2014-09-16 13:10:54 -07:00
Ian Bradley
306f4ef46b Added escapeshellarg() for WebM thumbnail generation. 2014-09-15 16:57:06 -07:00
Ian Bradley
0a9de3deb5 FFmpeg support for WebMs. Fixes threads with large amounts of WebM's causing crashes for some users. 2014-09-15 16:34:36 -07:00
Ian Bradley
c1ecef3772 Added support for BSD md5 incase md5sum isn't available. 2014-09-15 16:33:37 -07:00
8chan
66e026b361 ?/bans: fix pagination - can now see all bans on all boards if > $config[mod][banlist_page]
Conflicts:
	inc/bans.php
2014-09-13 16:43:46 +00:00
Fredrick Brennan
39cecea579 Merge pull request #77 from juanchan/smallfixes
optionally show mod name in templates/banned.html
2014-09-01 10:33:47 -04:00
Juan Tamad
53ada6a5ff added option for showing the mod in ban page.
also fixes issue where the Staff is not shown in ban appeals.
2014-09-01 06:30:33 +08:00
Tomasz Konojacki
f7b6693c02 Merge pull request #75 from xenu/master
added support for statcounter.com tracking code
2014-08-24 23:40:19 +02:00
Tomasz Konojacki
1b62fbea6f added support for statcounter.com tracking code 2014-08-24 23:33:53 +02:00
Marcin Łabanowski
d78dcd6ed6 fix a bug reported by Dudeman on #v-d 2014-08-21 04:27:47 +02:00
czaks
4d7933deb8 fix hide-threads.js & no-animated-gif.js interaction 2014-08-10 22:54:47 +02:00
czaks
1a1d44aadf live-index: fix for boards with more than one letter in name 2014-08-10 22:49:23 +02:00
czaks
48c1de637c live-index.js: load new thread functionality; bugfixes 2014-08-10 22:47:05 +02:00
czaks
e1d99e66b5 hide-threads.js: hide field from live-index as well 2014-08-10 22:45:12 +02:00
czaks
169d088c50 increase waiting times for watch.js and live-index.js 2014-08-10 21:00:31 +02:00
czaks
4d25ca85ce live-index.js: initial commit 2014-08-10 20:55:37 +02:00
czaks
5cd435f176 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-08-10 18:44:59 +02:00
Marcin Łabanowski
91519d9052 hopefully optimize watch.js a lot. fixes #24 2014-08-10 18:44:23 +02:00
8chan
e28f233e3d Close #51: Prevent players from cheating the dice roller by using markup 2014-08-10 15:38:02 +00:00
8chan
1ea3da1db6 Merge Barrucadu/diceroll into master 2014-08-10 15:35:11 +00:00
Marcin Łabanowski
eeeec608b9 Merge pull request #74 from kpcyrd/vichan-player
Suppress warnings that might leak information in player.php
2014-08-09 15:49:38 +02:00
kpcyrd
33c6d6644e Suppress warnings that might leak information 2014-08-09 12:14:56 +02:00
kpcyrd
bf52d41650 Improve type-safty in player.php 2014-08-09 12:14:12 +02:00
czaks
c3662d4a59 handle tinyboard flags with length=0 2014-08-09 05:12:36 +02:00
czaks
1b2f512339 final solution to expand-too-long problems 2014-08-09 04:56:50 +02:00
czaks
7da6f3b212 styling: webm-settings: remove extraneous <span> 2014-08-08 23:24:04 +02:00
czaks
ff1ea29755 fix imgops size in a futaba+vichan style 2014-08-08 23:14:12 +02:00
czaks
2c99ede62f fix html validity 2014-08-08 23:09:33 +02:00
czaks
bc5858fe83 image id buttons should be smaller 2014-08-08 23:08:02 +02:00
czaks
05e7ad0b56 ongoing catalog cleanup 2014-08-08 22:50:31 +02:00
czaks
f5191151ef fix catalog a little more; remove tooltipster (it didn`t work) and order by last reply date (mostly redundant); now the generation times are a little bit better 2014-08-08 22:44:02 +02:00
czaks
4df5d7697d fix & optimize catalog a little bit, don't expect anything big yet 2014-08-08 22:36:36 +02:00
czaks
b8381b31db Revert "Use a different way to show the original filename"
This reverts commit d81a6c49e28133c65d237fc648be7fe323bfd54d.

Conflicts:
	js/download-original.js
	templates/post/fileinfo.html
2014-08-08 22:18:06 +02:00
czaks
84c8e74ffa Revert "I thought I deleted that"
This reverts commit c6e1afcf650e55d1f64867440fcd623d386f922f.
2014-08-08 22:09:28 +02:00
Jano Slota
31f0c1f1e3 Open image identification links in new tabs 2014-08-08 21:59:06 +02:00
Jano Slota
c6e1afcf65 I thought I deleted that 2014-08-08 21:58:49 +02:00
Jano Slota
46c07d3566 Change styling of fileinfo, add iqdb search 2014-08-08 21:58:15 +02:00
Jano Slota
a87dc24169 Minor fixes for embed htmls 2014-08-08 21:57:58 +02:00
Jano Slota
3144e11cf9 Minor fixes for embed htmls 2014-08-08 21:57:11 +02:00
czaks
96f5770e2e leave the download-original js for compatibility 2014-08-08 21:56:15 +02:00
Jano Slota
cadfa2cee9 Do not show noko in email selectbox if it's disabled 2014-08-08 21:53:21 +02:00
kaf
fd58873ee6 Added a space for valid html5 2014-08-08 21:53:00 +02:00
Jano Slota
d65adac580 inline-expanding.js: 98% it is 2014-08-08 21:52:48 +02:00
Jano Slota
f14922ca8b inline-expanding.js: Or is it not after all? 2014-08-08 21:52:33 +02:00
Jano Slota
d81a6c49e2 Use a different way to show the original filename
Conflicts:
	templates/post/fileinfo.html
2014-08-08 21:52:19 +02:00
Jano Slota
8d8f66c701 inline-expanding.js: maxWidth is pointless now 2014-08-08 21:48:56 +02:00
Alrahambra
323f29d2b3 update fi_FI locale 2014-08-08 21:48:02 +02:00
dubcheck
bbff6da4c8 update sk_SK locale 2014-08-08 21:47:10 +02:00
cicus
34d4e3267a update hu_HU locale 2014-08-08 21:46:35 +02:00
Adverso
31420d4190 update es_ES locale 2014-08-08 21:45:39 +02:00
copypaste
4dba56386d update eo locale 2014-08-08 21:44:56 +02:00
kennyl
b81f9749a8 update zh_TW locale 2014-08-08 21:44:08 +02:00
kaf
c6c7de937a update fr_FR locale 2014-08-08 21:43:18 +02:00
Jano Slota
4fa98d938a Fix save-user_flag.js
Conflicts:
	js/save-user_flag.js
2014-08-08 21:39:20 +02:00
kpcyrd
9a98d518a0 Fix is_writable check for templates/cache 2014-08-08 21:36:56 +02:00
czaks
fa198e207f enhance filters; make them work on multiimage 2014-08-08 21:35:00 +02:00
czaks
57e80951d9 sorta document the changes in config.php 2014-07-28 04:15:09 +02:00
czaks
a01f8e9e11 actually allow for a log-only filter 2014-07-28 04:12:19 +02:00
czaks
50091e28a9 allow the previous not only for ban action, but also for reject action, or a nul one 2014-07-28 04:09:01 +02:00
czaks
a940ee9abb Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-07-28 04:06:39 +02:00
Marcin Łabanowski
29e71fa3ee filters: add option to log a message body in ip notes 2014-07-28 04:05:47 +02:00
8chan
48f99deaa5 Fix post linking bug in ?/recent 2014-07-21 16:55:36 +00:00
Fredrick Brennan
18f158e2d5 Forgot some |e 2014-07-19 18:47:34 +00:00
8chan
ef7556194c Fix 55ch cancer; can now see next page of posts, ?/recent uses templating system 2014-07-19 18:42:52 +00:00
czaks
8d0f1bf4ad fix a bug in filename truncation 2014-07-08 09:56:31 +02:00
czaks
f97d2dff85 fix previous commit 2014-07-08 09:44:30 +02:00
czaks
9526f5ed1c fix #72 2014-07-08 09:43:04 +02:00
czaks
b26cd8b9b4 Merge 4.5 and branch for 4.9.91 2014-07-08 01:57:02 +02:00
czaks
3ef5e9c0c8 tag for vichan-4.5.2 2014-07-08 01:40:58 +02:00
czaks
8d3c3f7ef7 Merge 4.5 2014-07-06 03:58:00 +02:00
czaks
4a0c87c7e1 Revert "Update jQuery UI to 1.11.0, GeoIPv6 and IP library"
This reverts commit dca7570b32c6d17024684f99371b0659d785b02e.
2014-07-06 03:50:16 +02:00
czaks
4881575b39 Revert "Oekaki's going to work now. Trust me"
This reverts commit 7b339f7f56d2d4fdbddceef385d874cb3cf936d1.
2014-07-06 03:49:49 +02:00
czaks
d38433a9c2 fix gzip static 2014-07-06 03:22:40 +02:00
czaks
9b943da60a Revert "Rework the GeoIP code, add country-based poster names"
This reverts commit db3c7f4ee984002fccb86e0cb3fda45edde74351.
2014-07-06 02:13:08 +02:00
czaks
a9b035d822 Revert "Second rework of the GeoIP code, now supporting cities!"
This reverts commit 2488e77e86edc3bb2b24377b25e8439f35cc2343.
2014-07-06 02:12:54 +02:00
Jano Slota
d1a3fe6dbf Fix save-user_flag.js 2014-07-06 01:31:22 +02:00
Jano Slota
23fc32f835 Add save-user_flag.js 2014-07-06 01:31:00 +02:00
Jano Slota
2488e77e86 Second rework of the GeoIP code, now supporting cities! 2014-07-06 01:30:38 +02:00
Jano Slota
a1d2d2388a Fix the bug that allowed to post an empty reply 2014-07-06 01:29:30 +02:00
Jano Slota
db3c7f4ee9 Rework the GeoIP code, add country-based poster names 2014-07-06 01:29:12 +02:00
Jano Slota
4adf893c39 Random names for anonymous users - thanks to svnth 2014-07-06 01:27:38 +02:00
Jano Slota
7b339f7f56 Oekaki's going to work now. Trust me 2014-07-06 01:26:17 +02:00
Jano Slota
dca7570b32 Update jQuery UI to 1.11.0, GeoIPv6 and IP library 2014-07-06 01:25:37 +02:00
czaks
6a3dbe5c98 Merge 4.5
Conflicts:
	inc/display.php
	templates/post_reply.html
	templates/post_thread.html
2014-07-06 01:24:16 +02:00
czaks
1853efa883 SECURITY: backport fix for #70 for 4.5. reported by Barrucadu 2014-07-06 01:20:42 +02:00
8chan
f2809d4793 Fix issue #45 2014-07-06 01:14:59 +02:00
Jano Slota
b21eccfd90 Is that a typo? 2014-07-06 01:13:07 +02:00
Chen-Pang He
97069ea490 Introduce $config['gzip_static'] 2014-07-06 01:12:12 +02:00
Marcin Łabanowski
95bb7b84b7 actually fix #70 2014-07-06 01:07:41 +02:00
Marcin Łabanowski
fcf3863d47 Merge pull request #70 from Barrucadu/title-injection
Fix unsanitised text vulnerability in post/fileinfo.html
2014-07-05 23:01:37 +02:00
Michael Walker
8aff83bdd4 Fix unsanitised text vulnerability in post/fileinfo.html 2014-07-05 21:57:06 +01:00
8chan
9df6ca8ddd Fix issue #45 2014-06-24 19:41:00 +00:00
czaks
4eec65782e Merge 4.5
Conflicts:
	install.php
2014-06-21 21:27:01 +02:00
czaks
f4fd816202 tag for 4.5.1 2014-06-21 21:14:51 +02:00
czaks
a04dee562c update locales for 5.0 2014-06-21 21:04:29 +02:00
czaks
3895223922 Merge 4.5
Conflicts:
	templates/post_thread.html
2014-06-21 20:50:41 +02:00
czaks
99e51421c2 remove license exception for Tinyboard vanilla, since they moved to a different one 2014-06-21 20:49:13 +02:00
Chen-Pang He
9fd003cbca import zh_TW translation 2014-06-21 20:46:30 +02:00
mgaj
0adc70baf7 update es_ES locale 2014-06-21 20:40:14 +02:00
sildeperker
3241f6325b import da_DK transation 2014-06-21 20:39:33 +02:00
kaf
4f61279ad6 update fr_FR transation 2014-06-21 20:38:51 +02:00
czaks
32c42e3596 update pl_PL translation 2014-06-21 20:38:16 +02:00
8chan
8d8563a20d Fix scroll to issues with post-hover.js, clean up highlightReply
Conflicts:
	templates/post_reply.html
	templates/post_thread.html
2014-06-21 20:34:09 +02:00
czaks
26884e8e11 Merge 4.5
Conflicts:
	post.php
2014-06-20 23:35:45 +02:00
czaks
73177fcffc Merge branch '4.5' of github.com:vichan-devel/Tinyboard into HEAD
Conflicts:
	templates/themes/basic/index.html
2014-06-20 23:27:34 +02:00
Techan
9e2b722db6 Change timezone of news on main page to local timezone 2014-06-20 23:26:17 +02:00
Techan
4cc8a0a8b0 Fix custom stylesheets on main page 2014-06-20 23:25:29 +02:00
Techan
c42050671b Improve main page template 2014-06-20 23:25:08 +02:00
Techan
eb2a468a09 Improve protection from displaying errors to visitors 2014-06-20 23:07:07 +02:00
Techan
8b7dd1acca Fix error in conditional operators priority 2014-06-20 23:06:26 +02:00
czaks
2c883fda0a fix ban appeals; thanks to sraczynski for reporting 2014-06-16 11:39:56 +02:00
czaks
8a189e2380 fix upgrade path a little bit with a new catalog 2014-06-16 11:29:18 +02:00
czaks
a4dc0d03b7 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-06-14 18:34:09 +02:00
czaks
b12612ac57 fix sql error as reported by a Romanian anon 2014-06-14 18:33:55 +02:00
8chan
91570ef083 Fix issue #57 2014-06-12 18:01:29 +00:00
8chan
a9765f6c4a Fix issue #61 2014-06-12 17:48:53 +00:00
8chan
e856917b00 Add scripts to catalog page 2014-06-12 17:27:18 +00:00
8chan
1d6f46d9bb Fix scroll to issues with post-hover.js, clean up highlightReply 2014-06-12 15:36:40 +00:00
czaks
427a9938a7 Merge 4.5 2014-06-12 03:12:56 +02:00
Chen-Pang He
7933abd271 Fix vichan #65
Conflicts:
	inc/mod/auth.php
	inc/mod/pages.php
2014-06-12 03:12:27 +02:00
czaks
030895d074 remove two extraneous fields from 4.5 to 5.0 migration 2014-06-11 03:40:00 +02:00
czaks
52e463a30a Merge branch 'master' of github.com:vichan-devel/Tinyboard
Conflicts:
	inc/mod/pages.php
2014-06-11 02:06:25 +02:00
czaks
503903ac0f Merge 4.5 2014-06-11 02:05:14 +02:00
czaks
23d6e82038 $_SERVER[HTTPS] isn`t being always set; fixes #65 2014-06-11 02:04:59 +02:00
Fredrick Brennan
4f070d16e5 Congrats, you broke the mod page on non-secured servers @jdh8 2014-06-10 23:09:39 +00:00
8chan
5a02cd61db Fix issue when loading images in Chrome 2014-06-10 18:50:44 +00:00
8chan
dfe8ddc340 Disable-able animated GIFs in a non-shitty way (unlike wizardchan) 2014-06-10 18:18:14 +00:00
czaks
e27c923b79 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-06-10 17:51:25 +02:00
czaks
c2cbbe7e22 Merge 4.5
Conflicts:
	js/expand-too-long.js
2014-06-10 17:51:03 +02:00
czaks
2f55cd9897 fix expand-too-long on some occasions 2014-06-10 17:49:12 +02:00
Chen-Pang He
6716a24b68 Send cookie only via HTTPS if a mod logs in via HTTPS, which is the case on this site 2014-06-10 17:42:18 +02:00
Chen-Pang He
8d745bec26 Set viewport to basic theme 2014-06-10 17:40:47 +02:00
Fredrick Brennan
9b170ceae7 Fix issue #63 for new migrations 2014-06-03 09:40:54 -04:00
8chan
b506c0be9f Fix array_filter error message when debug_stuff is false 2014-05-31 22:43:34 +02:00
czaks
c04b419639 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-05-28 15:37:36 +02:00
czaks
3ba152e0a1 revert mixitup update 2014-05-28 15:36:30 +02:00
8chan
073e6bec83 Fix array_filter error message when debug_stuff is false 2014-05-27 23:50:20 +00:00
8chan
eea984859b Better remote errors 2014-05-27 23:50:11 +00:00
8chan
76567cbd38 Fix expand-too-long.js for multifile 2014-05-23 23:55:19 +00:00
czaks
02f1514c70 fix single file metadata display in multifile; fixes #611 2014-05-21 09:05:35 +02:00
Fredrick Brennan
56695fbf04 No need for global config 2014-05-21 08:19:16 +02:00
Fredrick Brennan
f6e97b6e73 SECURITY: Remove $config[db][password] when $config[debug] is TRUE 2014-05-21 08:19:09 +02:00
Fredrick Brennan
696e5e59d2 Fix issue #60 2014-05-20 21:23:33 -04:00
Fredrick Brennan
007a770a73 Fix issue #58 2014-05-20 21:23:18 -04:00
Fredrick Brennan
bd94d0c392 Fix inline epxanding of videos 2014-05-19 14:18:46 -04:00
Fredrick Brennan
0be16cf178 Fix js error when allow_delete is false 2014-05-19 14:11:24 -04:00
Fredrick Brennan
65a14a0d39 Fix moving of deleted files 2014-05-19 14:00:16 -04:00
Fredrick Brennan
85136b76ed No need for global config 2014-05-19 13:46:18 -04:00
Fredrick Brennan
ff809ccf71 SECURITY: Remove $config[db][password] when $config[debug] is TRUE 2014-05-19 13:39:30 -04:00
Fredrick Brennan
101202a031 Fix edit board link not appearing 2014-05-18 21:18:06 -04:00
Fredrick Brennan
c1bc5778dd Derp, filesize was always being based on first file 2014-05-17 15:47:15 -04:00
czaks
ea47e000f4 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-05-16 10:47:16 +02:00
Jano Slota
ecbf1ff24c Fixed image identification 2014-05-16 10:47:10 +02:00
Jano Slota
c67f4ba897 Updated Font Awesome to 4.1.0 2014-05-16 10:46:53 +02:00
Fredrick Brennan
9b3f8421fc Fix displaying bans 2014-05-14 13:51:49 -04:00
Marcin Łabanowski
0da65c3d7b Merge pull request #55 from itsCrafted/patch-1
Make post.php compatable with PHP 5.3x
2014-05-13 22:30:42 +02:00
Reid 'Crafted'
78ffd76fcf Make post.php compatable with PHP 5.3x
Compatible with earlier versions of PHP. This should work on 5.4 too, but I haven't tested it.
2014-05-13 21:23:06 +01:00
czaks
fe126cb4bf rewrite filename truncation code; ref #53 2014-05-11 14:10:53 +02:00
czaks
7d29cf9e37 Merge 4.5 2014-05-10 22:44:37 +02:00
kaf
c878b308bf update fr l10n 2014-05-10 22:44:22 +02:00
Aš Esu
6fbe26c9e1 update lt locale 2014-05-10 22:43:14 +02:00
diggydoc
8233cdbad2 update lv l10n 2014-05-10 22:42:20 +02:00
Alrahambra
1102e6d47c update fi l10n 2014-05-10 22:40:47 +02:00
neniu
d7a20417bd update eo l10n 2014-05-10 22:39:56 +02:00
Assada
8103a0ba8d update ru l10n 2014-05-10 22:39:21 +02:00
cicus
65a87ed9af update hu l10n 2014-05-10 22:38:43 +02:00
czaks
18a2017b7a Merge ../pl
Conflicts:
	install.php
2014-05-10 22:06:22 +02:00
czaks
61ec084ee6 tag for vichan-4.5.0 2014-05-10 22:04:09 +02:00
czaks
4288898dfa Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-05-10 21:58:34 +02:00
czaks
19ce50c545 Merge ../pl
Conflicts:
	post.php
2014-05-10 21:58:23 +02:00
Marcin Łabanowski
7b57a4b911 Merge pull request #53 from 3edgy6u/master
Truncate filenames properly
2014-05-10 21:55:04 +02:00
Jano Slota
844d724b62 Optimized images 2014-05-10 21:51:00 +02:00
Jano Slota
c2c7859a9e Fixed a little exiftool bug
Conflicts:
	post.php
2014-05-10 21:50:01 +02:00
Jason Lam
ff51706bfd add new truncate_filename filter 2014-05-09 20:42:57 -04:00
Jason Lam
eca5c383e1 added truncate_filename function 2014-05-09 20:42:05 -04:00
Jason Lam
9bd0572b63 use new truncate_filename function 2014-05-09 20:37:31 -04:00
Jason Lam
bf7304622a Update poster_id.html
previous code did not work
2014-05-08 00:58:42 +02:00
Marcin Łabanowski
a6b8a73be4 Merge pull request #52 from 3edgy6u/master
fixed poster_ids
2014-05-08 00:55:54 +02:00
Jason Lam
9dab9179f9 Update poster_id.html
previous code did not work
2014-05-07 18:37:48 -04:00
Jano Slota
c25b8f01c5 Updated minify, jQuery, MixItUp and Tooltipster 2014-05-07 11:17:32 +02:00
Jano Slota
593560956c Added configurabe image identification 2014-05-07 11:14:30 +02:00
czaks
cd15458a32 Merge remote-tracking branch 'origin/4.5' 2014-05-06 21:53:38 +02:00
czaks
f7278e5a61 user moderation support 2014-05-06 21:53:05 +02:00
Fredrick Brennan
d31a353962 Allow post deletion switch 2014-05-05 18:03:51 -04:00
Marcin Łabanowski
7f725713a1 Merge pull request #50 from Barrucadu/autoreload-cooldown
Autoreload cooldown
2014-05-05 23:39:28 +02:00
Michael Walker
abaf80fd8a Reset the delay to the minimum upon focussing the window (configurable) 2014-05-05 20:54:40 +01:00
Michael Walker
54fdd54e89 Make the delays configurable in settings.js 2014-05-05 20:51:51 +01:00
Michael Walker
97cfec836b Add a maximum reload delay 2014-05-05 19:33:57 +01:00
Michael Walker
91a3016d27 Increase the poll_interval_delay when there are no posts 2014-05-05 19:33:57 +01:00
Michael Walker
0e18636fe6 Move the magic numbers out to variables 2014-05-05 19:33:57 +01:00
czaks
8f021a35a6 i knew that i broke it... 2014-05-05 18:07:13 +02:00
czaks
81c3f02d28 warn about moving to 5.0 branch 2014-05-05 17:53:31 +02:00
czaks
72c7e28a0e Merge branch 'master' into staging 2014-05-05 17:29:59 +02:00
czaks
e3ac13289d Merge branch 'staging' of github.com:vichan-devel/Tinyboard into staging 2014-05-05 17:29:52 +02:00
czaks
855618b2a0 Merge branch 'master' of github.com:vichan-devel/Tinyboard
Conflicts:
	templates/themes/catalog/catalog.html
	templates/themes/catalog/theme.php
2014-05-05 17:29:34 +02:00
czaks
ab52741a5f catalog.js: should be used only in catalog view 2014-05-05 17:23:49 +02:00
Fredrick Brennan
5039584a5e Fix ?/recent str_replace issue 2014-05-04 19:24:34 -04:00
Fredrick Brennan
664daf8571 Merge branch 'staging' of https://github.com/vichan-devel/vichan into staging 2014-05-04 19:11:43 -04:00
Fredrick Brennan
ac31698b0d Fix hide-images.js for multiimage 2014-05-04 19:11:23 -04:00
czaks
81b0612d56 fug, i replaced finnish locale with pt_BR? 2014-05-04 02:13:37 +02:00
czaks
73eb8c6b58 quick & dirty youtube thumbnails in catalog support 2014-05-04 01:20:12 +02:00
czaks
bac23d22f8 forgot to compile lv_LV locale ;_; 2014-05-04 00:24:12 +02:00
czaks
dafe0d5896 Merge branch 'master' of github.com:vichan-devel/Tinyboard into staging 2014-05-04 00:19:45 +02:00
diggydoc
90666e3674 preliminary lv_LV l10n 2014-05-04 00:17:05 +02:00
neniu
24c31b402a finalize esperanto l10n 2014-05-04 00:13:28 +02:00
czaks
45fdd71b63 fix it more 2014-05-04 00:05:55 +02:00
czaks
8d4104feb0 restore php5.3 compatibility. thx for Kihokki for reporting that 2014-05-03 23:58:24 +02:00
czaks
211c1acec9 actually fix this bug 2014-05-02 19:32:18 +02:00
czaks
9416587d40 fix a bug with multiple images; thanks to saiko of tahta.ch for reporting it 2014-05-02 18:58:21 +02:00
Fredrick Brennan
b1912ba86f Merge branch 'staging' of https://github.com/vichan-devel/vichan into staging 2014-04-30 17:18:44 -04:00
Fredrick Brennan
042e7b9c59 Deprecate postControls(), per-file deletion and spoilering 2014-04-30 17:18:35 -04:00
czaks
0a53fdb3a2 remove quick-reply harder 2014-04-30 22:46:20 +02:00
czaks
4e21e3dbb7 Merge master branch into staging
Conflicts:
	templates/themes/ukko/theme.php
2014-04-30 18:28:46 +02:00
czaks
3545ba1b47 ukko: this return thingy wasn`t needed 2014-04-30 18:28:14 +02:00
czaks
318d75ac27 ukko: mod support for ukko; fixes #23 2014-04-30 18:20:30 +02:00
czaks
776bbeb73e ukko: mod support for ukko; fixes #23 2014-04-30 18:18:55 +02:00
Fredrick Brennan
400df0975f Fix upload-selection for multifile 2014-04-30 10:27:24 -04:00
Fredrick Brennan
dedc531adc Fix inline expanding issue with new styles 2014-04-30 10:21:02 -04:00
Fredrick Brennan
de524c64d9 Attempt to fix styling issue http://i.imgur.com/owHv6sE.png 2014-04-29 20:39:32 -04:00
Fredrick Brennan
24753907eb remove var_dump 2014-04-29 20:18:30 -04:00
Fredrick Brennan
0c9a27e165 Merge branch 'staging' of https://github.com/vichan-devel/vichan into staging 2014-04-29 19:14:26 -04:00
Fredrick Brennan
53e33d414f Fix mod_move for multi image 2014-04-29 19:14:10 -04:00
Fredrick Brennan
2b3942d19d Fix mod_move for multi image 2014-04-29 19:07:13 -04:00
Fredrick Brennan:w
8a73c084de Add webm support to README 2014-04-30 00:36:09 +02:00
Fredrick Brennan:w
c5576120d9 Oekaki instructions 2014-04-30 00:36:05 +02:00
czaks
2adf7d99db integrate favelog into catalog theme; needs more work, code cleanup etc. 2014-04-30 00:14:25 +02:00
czaks
bb5446a93d Merge remote-tracking branch 'origin/br-integration' into staging 2014-04-29 21:35:50 +02:00
czaks
c1aaf78cbb forgot one place to remove quick-reply-old 2014-04-29 21:35:45 +02:00
Fredrick Brennan
8e81c8c669 Merge branch 'staging' of https://github.com/vichan-devel/vichan into staging 2014-04-29 15:20:42 -04:00
czaks
a2d62ce96d fix webm for multiimage 2014-04-29 21:18:37 +02:00
czaks
46802d3f1b fix post event 2014-04-29 21:18:17 +02:00
Fredrick Brennan:w
0557c21845 Add webm support to README 2014-04-29 15:01:34 -04:00
Fredrick Brennan:w
6a1a979ae7 Oekaki instructions 2014-04-29 14:59:17 -04:00
czaks
d57dcc5e6e fix remote upload 2014-04-29 20:50:28 +02:00
czaks
a53f52696e remove post-hider symlink 2014-04-29 20:15:57 +02:00
czaks
18092de0c4 Merge ../pl into staging 2014-04-29 19:53:29 +02:00
czaks
15a65caf9d update wpaint; fix wpaint.js 2014-04-29 19:45:30 +02:00
czaks
b7112050a1 Merge branch 'master' of github.com:vichan-devel/Tinyboard into staging 2014-04-29 18:59:14 +02:00
neniu
eb23552531 update eo l10n 2014-04-29 18:57:37 +02:00
czaks
4287822229 limit the cli debug uptput 2014-04-29 18:48:57 +02:00
czaks
18e9c32a0e limit the cli debug uptput 2014-04-29 18:48:21 +02:00
czaks
b94e39148b remove quick-reply-old. it probably doesn't work now, it certainly isn't
maintained. this is an old cruft and if needed, it needs rewriting.
2014-04-29 18:37:29 +02:00
czaks
d208789fa7 remove attentionbar. its code is shit and it doesn't belong here tbh. 2014-04-29 18:33:03 +02:00
copypaste
613c64c97d fix upgrade path 2014-04-27 17:18:42 +02:00
copypaste
c0e82e077f fix upgrade path 2014-04-27 17:01:57 +02:00
copypaste
a96f28afc0 fix upgrade path 2014-04-27 17:00:37 +02:00
czaks
684e886f14 Merge remote-tracking branch 'origin/master' into staging 2014-04-27 16:26:52 +02:00
czaks
932c451f9e display backtrace when error on rebuilding from CLI 2014-04-27 16:26:08 +02:00
Vespero
7bf662460c update eo locale 2014-04-27 16:23:44 +02:00
neniu
4bc03a560c update eo locale 2014-04-27 16:23:09 +02:00
MartenŜadoko
19ebd82abc update eo locale 2014-04-27 16:22:52 +02:00
czaks
276a742bce Revert "change thumb to file to overcome a nasty bug in upgrading"
This reverts commit b0faa1a7e40e1d193c64dcfcffd38cdb594c13a6.
2014-04-27 16:19:41 +02:00
czaks
a236a17308 multi_image.js -> multi-image.js 2014-04-27 16:13:13 +02:00
czaks
b0faa1a7e4 change thumb to file to overcome a nasty bug in upgrading 2014-04-27 16:05:38 +02:00
czaks
28b9584a7b display backtrace when error on rebuilding from CLI 2014-04-27 16:01:41 +02:00
czaks
6685333bd3 don‘t abort upgrade if REBUILD isn‘t supported 2014-04-27 15:57:51 +02:00
copypaste
c483e1258c multiimage posting 2014-04-27 15:48:47 +02:00
neniu
7a04150b04 Esperanto l10n 2014-04-23 23:23:57 +02:00
Tunai
b516661097 update tr_TR locale 2014-04-22 23:23:02 +02:00
Assada
cc29f9879b update ru_RU locale 2014-04-22 23:22:20 +02:00
copypaste
55a6047b85 update es_ES locale 2014-04-22 23:21:22 +02:00
dubcheck
fa3738ba28 update sk_SK translation 2014-04-22 15:20:07 +02:00
cookiezeater
fcf1743af8 update ru_RU translation 2014-04-22 13:26:08 +02:00
cicus
4098d2a808 update hu_HU locale 2014-04-22 13:24:37 +02:00
czaks
2b2fa390c5 Merge branch 'master' of https://github.com/savetheinternet/Tinyboard
Conflicts:
	js/expand.js
2014-04-22 08:57:39 +02:00
czaks
31185ab4c9 update locales from transifex 2014-04-22 08:49:40 +02:00
Michael
037ce6bfac Merge pull request #159 from rikukissa/master
change finnish locale contact email
2014-04-22 08:16:01 +10:00
Michael
de395fcc36 Merge pull request #166 from joosera/master
Fix js/expand.js
2014-04-22 08:15:34 +10:00
Michael
fcea494198 Merge pull request #168 from undido/master
Removed gettext libary's examples and tests folder xss exploit fix
2014-04-22 08:15:28 +10:00
czaks
30eac1703a add donation info to readme.md 2014-04-21 17:15:06 +02:00
czaks
a9c35844c7 fix themes resetting the board 2014-04-21 15:38:18 +02:00
czaks
4a3dd0cfd6 config.php: i18n one more message 2014-04-21 02:41:01 +02:00
czaks
6379e024a6 compact-boardlist.js: allow direct board links 2014-04-21 01:19:34 +02:00
czaks
366a72a813 update hu_HU locale 2014-04-21 00:52:37 +02:00
czaks
0ec6355358 fix recentposts theme building null query, throw error instead 2014-04-20 23:33:52 +02:00
czaks
d25db31860 Merge branch 'master' of github.com:vichan-devel/Tinyboard 2014-04-20 23:16:24 +02:00
czaks
b87d3d76d5 improve debugging 2014-04-20 23:16:15 +02:00
czaks
e2cd1d9372 update locales hu_HU, pl_PL and sk_SK from transifex 2014-04-20 21:29:15 +02:00
czaks
4f5ba1d822 tag for 4.4.98 fixes #47 2014-04-20 02:49:25 +02:00
czaks
a93530e32f update copyright footers in themes 2014-04-20 02:27:54 +02:00
czaks
8665f7b129 update locales 2014-04-20 00:58:33 +02:00
czaks
66d0c08d8e load german locale from transifex 2014-04-19 23:44:11 +02:00
czaks
edcaee1f78 treeview.js: initial commit 2014-04-19 23:33:54 +02:00
czaks
b33e8cb10d fix previous commit 2014-04-19 23:06:59 +02:00
ctrlcctrlv
465986d06c use all boards for search.php if boards are not specified 2014-04-19 23:03:23 +02:00
czaks
7eb2bef107 expand-too-long.js: initial commit 2014-04-19 21:48:27 +02:00
czaks
1b8efaee8c added my copyrights 2014-04-19 21:26:04 +02:00
czaks
b0ac5b17d4 fix show-op.js 2014-04-19 21:23:35 +02:00
czaks
8fb70d1196 update readme 2014-04-19 20:42:22 +02:00
czaks
7e30f1d3cf add user_flag to valid inputs 2014-04-19 19:17:03 +02:00
kaf
b102fd5f4e Typo
Conflicts:
	inc/config.php
2014-04-19 18:49:12 +02:00
kaf
f83c87b623 Added: /pol/-like flags based on a953229de7
Conflicts:
	inc/config.php
	templates/post_form.html
2014-04-19 18:48:17 +02:00
czaks
17967436e3 pull hu_HU and ru_RU locales from transifex 2014-04-19 17:33:25 +02:00
czaks
0f0a19ad4c update pt_BR translation 2014-04-19 01:06:34 +02:00
czaks
c8cec2824a update pt_BR translation 2014-04-19 00:50:49 +02:00
czaks
cd34871480 update pt_BR l18n by hitmonkey 2014-04-19 00:36:24 +02:00
undido
afa62e7836 Removed gettext libary's examples and tests folder 2014-04-05 20:46:10 -03:00
joosera
d2aaf9e63a Fix js/expand.js
Fixed missing end tags and changed .text to .html since .text strips HTML
2014-04-04 03:24:01 +01:00
Riku Rouvila
6dcc224f11 change finnish locale contact email 2014-01-09 20:11:40 +02:00
978 changed files with 122637 additions and 40222 deletions

4
.dockerignore Normal file
View File

@ -0,0 +1,4 @@
**/.git
**/.gitignore
/local-instances
**/.gitkeep

69
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,69 @@
name: Bug Report
description: File a bug report for Vichan
title: "[BUG] "
labels: ["bug"]
assignees: []
body:
- type: markdown
attributes:
value: |
**Thank you for reporting a bug! Please provide as much detail as possible.**
Before submitting, check the [Vichan Wiki](https://vichan.info) to see if there's already a solution to your problem.
- type: textarea
id: bug_description
attributes:
label: "Describe the bug"
description: "A clear and concise description of what the bug is."
placeholder: "Posting doesn't go through and displays a collation error. The exact error message given is the text below and I've attached a screenshot..."
validations:
required: true
- type: textarea
id: steps_to_reproduce
attributes:
label: "Steps to Reproduce"
description: "Provide step-by-step instructions to reproduce the issue. If you're unsure on how, that is alright, just try and explain as well as you can."
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
render: markdown
validations:
required: true
- type: textarea
id: expected_behavior
attributes:
label: "Expected Behavior"
description: "What did you expect to happen?"
placeholder: "Expected behavior here..."
render: markdown
validations:
required: true
- type: textarea
id: server_specs
attributes:
label: "Server Specifications"
description: "Provide details about your server environment. If you're unsure about any of this, you might be using shared hosting (Hostinger, HostGator, Serv00, etc). If so, put the name of your hosting provider here."
placeholder: |
- OS: (Ubuntu, CentOS, Windows Server 2025, etc.)
- PHP Version: (e.g., 7.4, 8.0, 8.4)
- Web Server: (Apache, NGINX, etc.)
- Database: (MySQL, MariaDB, etc.)
- Vichan Version: (5.2.0, 5.3.0 (dev branch), etc)
render: markdown
validations:
required: true
- type: textarea
id: additional_context
attributes:
label: "Additional Context"
description: "Any other details we should know?"
placeholder: "Add any additional context here..."
render: markdown

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

14
.gitignore vendored
View File

@ -11,11 +11,8 @@
!/templates/*.html
!/inc/config.php
# minify
/inc/lib/minify
# instance-config
/inc/instance-config.php
/inc/secrets.php
# .installed
/.installed
@ -38,6 +35,15 @@ Thumbs.db
*.orig
*~
# tmp filesystem
/tmp/cache/*
/tmp/locks/*
!/tmp/cache/.gitkeep
!/tmp/locks/.gitkeep
#vichan custom
favicon.ico
/static/spoiler.png
/local-instances
/vendor/

9
.gitmodules vendored
View File

@ -1,3 +1,12 @@
[submodule "js/wPaint"]
path = js/wPaint
url = https://github.com/vichan-devel/wPaint.git
branch = master
[submodule "inc/lib/parsedown"]
path = inc/lib/parsedown
url = https://github.com/vichan-devel/parsedown.git
branch = master
[submodule "js/twemoji"]
path = js/twemoji
url = https://github.com/basedgentoo/twemoji

View File

@ -1,5 +1,5 @@
# License of vichan
Copyright (c) 2012-2014 vichan-devel
Copyright (c) 2012-2018 vichan-devel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -60,7 +60,3 @@ copyright notices untouched. Beside, we give you absolutely no guarantees.
Tinyboard and vichan licenses also clarify, that the copyright notices found
in the template footers are also covered by the copyright notice preservation
clause.
# Exception
It is explicitly allowed for the Tinyboard upstream, to take vichan
changesets under a Tinyboard license.

114
README.md
View File

@ -1,32 +1,50 @@
vichan - A lightweight and full featured PHP imageboard.
========================================================
**Please do not contact Fredrick Brennan in regards to vichan issues.**
As of 29 August 2022 it supports PHP8.1.
About
------------
vichan is a free light-weight, fast, highly configurable and user-friendly
imageboard software package. It is written in PHP and has few dependencies.
vichan is a fork of [Tinyboard](http://tinyboard.org/), a great imageboard package, actively building on it
and adding a lot of features and another improvements.
Some documentation may be found on our [wiki](https://github.com/vichan-devel/vichan/wiki). (feel free to contribute)
Support and announcements: https://int.vichan.net/devel/
History
------------
vichan is a fork of (now defunc'd) [Tinyboard](http://github.com/savetheinternet/Tinyboard),
a great imageboard package, actively building on it and adding a lot of features and other
improvements.
![](static/doc/timeline.svg)
### Maintainer timeline
1. [@perdedora](https://github.com/perdedora) and [@RealAngeleno](https://github.com/RealAngeleno) - 2023-Present.
2. Development Commission lead by [@basedgentoo](https://github.com/basedgentoo), [@kuz-sysadmin](https://github.com/kuz-sysadmin), and [@RealAngeleno](https://github.com/RealAngeleno). (2023 - 2023)
3. [@h00j](https://github.com/h00j) (2021 - ???)
4. [@ctrlcctrlv](https://github.com/ctrlcctrlv) (2017 - 2021)
5. [@czaks](https://github.com/czaks) (2014 - 2017) (The author of vichan fork)
6. [@savetheinternet](https://github.com/savetheinternet) (2010 - 2014) (The creator of Tinyboard)
Requirements
------------
1. PHP >= 5.3
1. PHP >= 7.4
2. MySQL/MariaDB server
3. [mbstring](http://www.php.net/manual/en/mbstring.installation.php)
4. [PHP GD](http://www.php.net/manual/en/intro.image.php)
5. [PHP PDO](http://www.php.net/manual/en/intro.pdo.php)
6. A Unix-like OS, preferrably FreeBSD or GNU/Linux
We try to make sure vichan is compatible with all major web servers and
operating systems. vichan does not include an Apache ```.htaccess``` file nor does
it need one.
We try to make sure vichan is compatible with all major web servers. vichan does not include an Apache `.htaccess` file nor does it need one.
### Recommended
1. MySQL/MariaDB server >= 5.5.3
2. ImageMagick (command-line ImageMagick or GraphicsMagick preferred).
3. [APC (Alternative PHP Cache)](http://php.net/manual/en/book.apc.php), [XCache](http://xcache.lighttpd.net/) or [Memcached](http://www.php.net/manual/en/intro.memcached.php)
3. [APCu (Alternative PHP Cache)](http://php.net/manual/en/book.apcu.php),
[Memcached](http://www.php.net/manual/en/intro.memcached.php) or
[Redis](https://redis.io/docs/about/)
Contributing
------------
@ -35,47 +53,47 @@ You can contribute to vichan by:
* Providing feedback and suggestions
* Writing/editing documentation
If you need help developing a patch, please join our IRC channel.
Installation
-------------
1. Download and extract Tinyboard to your web directory or get the latest
development version with:
1. Get the latest development version with:
git clone git://github.com/vichan-devel/vichan.git
2. Navigate to ```install.php``` in your web browser and follow the
2. run ```composer install``` inside the directory
3. Navigate to ```install.php``` in your web browser and follow the
prompts.
3. vichan should now be installed. Log in to ```mod.php``` with the
4. vichan should now be installed. Log in to ```mod.php``` with the
default username and password combination: **admin / password**.
Please remember to change the administrator account password.
See also: [Configuration Basics](http://tinyboard.org/docs/?p=Config).
See also: [Configuration Basics](https://github.com/vichan-devel/vichan/wiki/config).
Upgrade
-------
To upgrade from any version of Tinyboard or vichan:
Either run ```git pull``` to update your files, if you used git, or
backup your ```inc/instance-config.php```, replace all your files in place
(don't remove boards etc.), then put ```inc/instance-config.php``` back and
finally run ```install.php```.
To migrate from a Kusaba X board, use http://github.com/vichan-devel/Tinyboard-Migration
Demo
--------
Demo with the most updated version of [Vichan](https://vichan.27chan.org).
1. PHP 8.1
2. MySQL 5.7
3. KeyDB 6.2.1 (Redis)
4. NGINX 1.14.0
Support
--------
Tinyboard is still beta software -- there are bound to be bugs. If you find a
vichan is still beta software -- there are bound to be bugs. If you find a
bug, please report it.
If you need assistance with installing, configuring, or using vichan, you may
find support from a variety of sources:
* If you're unsure about how to enable or configure certain features, make
sure you have read the comments in ```inc/config.php```.
* Check out an [official vichan board](http://int.vichan.net/devel/).
* You can join vichan's IRC channel for support [irc.6irc.net #vichan-devel](irc://irc.6irc.net/vichan-devel)
Tinyboard support
-----------------
vichan is based on a Tinyboard, so both engines have very much in common. These
links may be helpful for you as well:
* Tinyboard documentation can be found [here](http://tinyboard.org/docs/).
* You can join Tinyboard's IRC channel for support and general queries:
[irc.datnode.net #tinyboard](irc://irc.datnode.net/tinyboard).
* You may find help at [tinyboard.org](http://tinyboard.org/#help).
CLI tools
-----------------
There are a few command line interface tools, based on Tinyboard-Tools. These need
@ -86,13 +104,31 @@ You actually don't need these tools for your imageboard functioning, they are ai
at the power users. You won't be able to run these from shared hosting accounts
(i.e. all free web servers).
Localisation
------------
Wanting to have vichan in your language? You can contribute your translations at this URL:
Oekaki
------
vichan makes use of [wPaint](https://github.com/websanova/wPaint) for oekaki. After you pull the repository, however, you will need to download wPaint separately using git's `submodule` feature. Use the following commands:
https://www.transifex.com/projects/p/tinyboard-vichan-devel/
```
git submodule init
git submodule update
```
To enable oekaki, add all the scripts listed in `js/wpaint.js` to your `instance-config.php`.
WebM support
------------
Read `inc/lib/webm/README.md` for information about enabling webm.
Docker
------------
Vichan comes with a Dockerfile and docker-compose configuration, the latter aimed primarily at development and testing.
See the `docker/doc.md` file for more information.
vichan API
----------
vichan provides by default a 4chan-compatible JSON API. For documentation on this, see:
https://github.com/vichan-devel/vichan-API/ .
License
--------
See [LICENSE.md](http://github.com/vichan-devel/vichan/blob/master/LICENSE.md).

View File

@ -1,11 +0,0 @@
<?php
require_once 'inc/functions.php';
checkBan();
$text = isset($_POST['text']) ? $_POST['text'] : '';
if(strlen($text)>0 && !preg_match('/a href/', $text)) {
file_put_contents("attentionbar.txt",htmlspecialchars($text));
if(strlen($_SERVER['HTTP_REFERER'])>0) { header('Location: ' . $_SERVER['HTTP_REFERER']); }
else { header('Location: /'); }
} else print(file_get_contents("attentionbar.txt"));
return;
?>

View File

@ -1 +0,0 @@
- * ( Pasek Atencji ) * -

8
b.php Normal file
View File

@ -0,0 +1,8 @@
<?php
$files = scandir('static/banners/', SCANDIR_SORT_NONE);
$files = array_diff($files, ['.', '..']);
$name = $files[array_rand($files)];
header("Location: /static/banners/$name", true, 307);
header('Cache-Control: no-cache');

View File

@ -1,7 +1,14 @@
<?php
require_once 'inc/functions.php';
checkBan();
print "<!doctype html><html><head><meta charset='utf-8'><title>"._("Banned?")."</title></head><body>";
print "<h1>"._("You are not banned.")."</h1>";
print "</body></html>";
require_once 'inc/bootstrap.php';
checkBan();
//If the user is not banned, show the "not banned" page.
die(
Element('page.html', array(
'title' => _('Not banned!'),
'config' => $config,
'nojavascript' => true,
'body' => Element('notbanned.html', array()
))
));
?>

40
compose.yml Normal file
View File

@ -0,0 +1,40 @@
services:
#nginx webserver + php 8.x
web:
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
ports:
- "9090:80"
depends_on:
- db
volumes:
- ./local-instances/${INSTANCE:-0}/www:/var/www/html
- ./docker/nginx/vichan.conf:/etc/nginx/conf.d/default.conf
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./docker/nginx/proxy.conf:/etc/nginx/conf.d/proxy.conf
links:
- php
php:
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./local-instances/${INSTANCE:-0}/www:/var/www
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
- ./docker/php/jit.ini:/usr/local/etc/php/conf.d/jit.ini
#MySQL Service
db:
image: mysql:8.0.35
container_name: db
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: vichan
MYSQL_ROOT_PASSWORD: password
volumes:
- ./local-instances/${INSTANCE:-0}/mysql:/var/lib/mysql

65
composer.json Normal file
View File

@ -0,0 +1,65 @@
{
"name": "vichan-devel/vichan",
"description": "vichan imageboard",
"type": "project",
"config": {
"platform": {
"php": "7.4"
}
},
"require": {
"php": ">=7.4",
"ext-mbstring": ">=7.4",
"ext-gd": ">=7.4",
"ext-pdo": ">=7.4",
"twig/twig": "^2.9",
"phpmyadmin/twig-i18n-extension": "^4.0",
"lifo/ip": "^1.0",
"gettext/gettext": "^5.5",
"mrclay/minify": "^2.1.6",
"geoip/geoip": "^1.17",
"dapphp/securimage": "^4.0",
"erusev/parsedown": "^1.7.4"
},
"autoload": {
"classmap": ["inc/"],
"files": [
"inc/bootstrap.php",
"inc/display.php",
"inc/template.php",
"inc/database.php",
"inc/events.php",
"inc/api.php",
"inc/mod/auth.php",
"inc/lock.php",
"inc/queue.php",
"inc/functions.php",
"inc/functions/dice.php",
"inc/functions/format.php",
"inc/functions/net.php",
"inc/functions/num.php",
"inc/functions/theme.php",
"inc/service/captcha-queries.php",
"inc/context.php"
]
},
"license": "Tinyboard + vichan",
"authors": [
{
"name": "savetheinternet",
"homepage": "https://github.com/savetheinternet"
},
{
"name": "czaks",
"homepage": "https://github.com/czaks"
},
{
"name": "ctrlcctrlv",
"homepage": "https://github.com/ctrlcctrlv"
},
{
"name": "h00j",
"homepage": "https://github.com/h00j"
}
]
}

757
composer.lock generated Normal file
View File

@ -0,0 +1,757 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "72e79f203581eea6e6b0455147b25878",
"packages": [
{
"name": "dapphp/securimage",
"version": "4.0.2",
"source": {
"type": "git",
"url": "https://github.com/dapphp/securimage.git",
"reference": "aabde76d839d75a238970661187f83312c2eeda7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dapphp/securimage/zipball/aabde76d839d75a238970661187f83312c2eeda7",
"reference": "aabde76d839d75a238970661187f83312c2eeda7",
"shasum": ""
},
"require": {
"ext-gd": "*",
"php": ">=5.4"
},
"suggest": {
"ext-pdo": "For database storage support",
"ext-pdo_mysql": "For MySQL database support",
"ext-pdo_sqlite": "For SQLite3 database support"
},
"type": "library",
"autoload": {
"psr-4": {
"Securimage\\": "./"
},
"classmap": [
"securimage.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Drew Phillips",
"email": "drew@drew-phillips.com"
}
],
"description": "PHP CAPTCHA Library",
"homepage": "https://www.phpcaptcha.org",
"keywords": [
"Forms",
"anti-spam",
"captcha",
"security"
],
"support": {
"issues": "https://github.com/dapphp/securimage/issues",
"source": "https://github.com/dapphp/securimage/tree/4.0.2"
},
"abandoned": true,
"time": "2020-05-30T10:05:48+00:00"
},
{
"name": "geoip/geoip",
"version": "v1.17",
"source": {
"type": "git",
"url": "https://github.com/maxmind/geoip-api-php.git",
"reference": "2053a85c2ed3e7adcbaf0117e26832f57366e370"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maxmind/geoip-api-php/zipball/2053a85c2ed3e7adcbaf0117e26832f57366e370",
"reference": "2053a85c2ed3e7adcbaf0117e26832f57366e370",
"shasum": ""
},
"conflict": {
"ext-geoip": "*"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
"satooshi/php-coveralls": "1.0.*"
},
"type": "library",
"autoload": {
"files": [
"src/geoip.inc",
"src/geoipcity.inc",
"src/timezone.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL 2.1+"
],
"authors": [
{
"name": "MaxMind, Inc.",
"email": "support@maxmind.com",
"homepage": "http://www.maxmind.com/"
}
],
"description": "MaxMind GeoIP PHP API",
"homepage": "http://dev.maxmind.com/geoip/legacy/downloadable",
"keywords": [
"geoip",
"geolocation",
"maxmind"
],
"support": {
"issues": "https://github.com/maxmind/geoip-api-php/issues",
"source": "https://github.com/maxmind/geoip-api-php/tree/master"
},
"abandoned": "geoip2/geoip2",
"time": "2016-05-16T19:06:50+00:00"
},
{
"name": "gettext/gettext",
"version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/php-gettext/Gettext.git",
"reference": "8657e580747bb3baacccdcebe69cac094661e404"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-gettext/Gettext/zipball/8657e580747bb3baacccdcebe69cac094661e404",
"reference": "8657e580747bb3baacccdcebe69cac094661e404",
"shasum": ""
},
"require": {
"gettext/languages": "^2.3",
"php": "^7.2|^8.0"
},
"require-dev": {
"brick/varexporter": "^0.3.5",
"friendsofphp/php-cs-fixer": "^3.2",
"oscarotero/php-cs-fixer-config": "^2.0",
"phpunit/phpunit": "^8.0|^9.0",
"squizlabs/php_codesniffer": "^3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Gettext\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oscar Otero",
"email": "oom@oscarotero.com",
"homepage": "http://oscarotero.com",
"role": "Developer"
}
],
"description": "PHP gettext manager",
"homepage": "https://github.com/php-gettext/Gettext",
"keywords": [
"JS",
"gettext",
"i18n",
"mo",
"po",
"translation"
],
"support": {
"email": "oom@oscarotero.com",
"issues": "https://github.com/php-gettext/Gettext/issues",
"source": "https://github.com/php-gettext/Gettext/tree/v5.7.0"
},
"funding": [
{
"url": "https://paypal.me/oscarotero",
"type": "custom"
},
{
"url": "https://github.com/oscarotero",
"type": "github"
},
{
"url": "https://www.patreon.com/misteroom",
"type": "patreon"
}
],
"time": "2022-07-27T19:54:55+00:00"
},
{
"name": "gettext/languages",
"version": "2.10.0",
"source": {
"type": "git",
"url": "https://github.com/php-gettext/Languages.git",
"reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-gettext/Languages/zipball/4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab",
"reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4"
},
"bin": [
"bin/export-plural-rules"
],
"type": "library",
"autoload": {
"psr-4": {
"Gettext\\Languages\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michele Locati",
"email": "mlocati@gmail.com",
"role": "Developer"
}
],
"description": "gettext languages with plural rules",
"homepage": "https://github.com/php-gettext/Languages",
"keywords": [
"cldr",
"i18n",
"internationalization",
"l10n",
"language",
"languages",
"localization",
"php",
"plural",
"plural rules",
"plurals",
"translate",
"translations",
"unicode"
],
"support": {
"issues": "https://github.com/php-gettext/Languages/issues",
"source": "https://github.com/php-gettext/Languages/tree/2.10.0"
},
"funding": [
{
"url": "https://paypal.me/mlocati",
"type": "custom"
},
{
"url": "https://github.com/mlocati",
"type": "github"
}
],
"time": "2022-10-18T15:00:10+00:00"
},
{
"name": "lifo/ip",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/lifo101/ip.git",
"reference": "4c4cf5b554884be93f1d0422eaec8d6426993229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lifo101/ip/zipball/4c4cf5b554884be93f1d0422eaec8d6426993229",
"reference": "4c4cf5b554884be93f1d0422eaec8d6426993229",
"shasum": ""
},
"require": {
"ext-bcmath": "*",
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Lifo\\IP\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jason Morriss",
"email": "lifo2013@gmail.com"
}
],
"description": "IP address helper PHP library for working with IPv4 and IPv6 addresses",
"keywords": [
"IP",
"ip address",
"ipv4",
"ipv6"
],
"support": {
"issues": "https://github.com/lifo101/ip/issues",
"source": "https://github.com/lifo101/ip/tree/v1.1.1"
},
"time": "2022-07-12T15:45:54+00:00"
},
{
"name": "mrclay/minify",
"version": "2.3.3",
"source": {
"type": "git",
"url": "https://github.com/mrclay/minify.git",
"reference": "1928e89208d28e91427b2f13b67acdbd8cd01ac9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mrclay/minify/zipball/1928e89208d28e91427b2f13b67acdbd8cd01ac9",
"reference": "1928e89208d28e91427b2f13b67acdbd8cd01ac9",
"shasum": ""
},
"require": {
"ext-pcre": "*",
"php": ">=5.2.1"
},
"require-dev": {
"tubalmartin/cssmin": "~2.4.8"
},
"suggest": {
"tubalmartin/cssmin": "Support minify with CSSMin (YUI PHP port)"
},
"type": "library",
"autoload": {
"classmap": [
"min/lib/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Stephen Clay",
"email": "steve@mrclay.org",
"role": "Developer"
}
],
"description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers",
"homepage": "http://code.google.com/p/minify/",
"support": {
"email": "minify@googlegroups.com",
"issues": "http://code.google.com/p/minify/issues/list",
"source": "https://github.com/mrclay/minify/tree/2.x",
"wiki": "http://code.google.com/p/minify/w/list"
},
"time": "2017-11-03T21:04:01+00:00"
},
{
"name": "phpmyadmin/twig-i18n-extension",
"version": "v4.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpmyadmin/twig-i18n-extension.git",
"reference": "c0d0dd171cd1c7733bf152fd44b61055843df052"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpmyadmin/twig-i18n-extension/zipball/c0d0dd171cd1c7733bf152fd44b61055843df052",
"reference": "c0d0dd171cd1c7733bf152fd44b61055843df052",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"twig/twig": "^1.42.3|^2.0|^3.0"
},
"require-dev": {
"phpmyadmin/coding-standard": "^3.0.0",
"phpmyadmin/motranslator": "^5.2",
"phpstan/phpstan": "^0.12.66",
"phpunit/phpunit": "^7 || ^8 || ^9"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpMyAdmin\\Twig\\Extensions\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "The phpMyAdmin Team",
"email": "developers@phpmyadmin.net",
"homepage": "https://www.phpmyadmin.net/team/"
}
],
"description": "Internationalization support for Twig via the gettext library",
"keywords": [
"gettext",
"i18n"
],
"support": {
"issues": "https://github.com/phpmyadmin/twig-i18n-extension/issues",
"source": "https://github.com/phpmyadmin/twig-i18n-extension"
},
"time": "2021-06-10T15:53:38+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "twig/twig",
"version": "v2.15.4",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "3e059001d6d597dd50ea7c74dd2464b4adea48d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3e059001d6d597dd50ea7c74dd2464b4adea48d3",
"reference": "3e059001d6d597dd50ea7c74dd2464b4adea48d3",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.8"
},
"require-dev": {
"psr/container": "^1.0",
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.15-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
},
"psr-4": {
"Twig\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Twig Team",
"role": "Contributors"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "https://twig.symfony.com",
"keywords": [
"templating"
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v2.15.4"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2022-12-27T12:26:20+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"ext-mbstring": ">=5.4",
"ext-gd": ">=5.4",
"ext-pdo": ">=5.4"
},
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

20
docker/doc.md Normal file
View File

@ -0,0 +1,20 @@
The `php-fpm` process runs containerized.
The php application always uses `/var/www` as it's work directory and home folder, and if `/var/www` is bind mounted it
is necessary to adjust the path passed via FastCGI to `php-fpm` by changing the root directory to `/var/www`.
This can achieved in nginx by setting the `fastcgi_param SCRIPT_FILENAME` to `/var/www/$fastcgi_script_name;`
The default docker compose settings are intended for development and testing purposes.
The folder structure expected by compose is as follows
```
<vichan-project>
└── local-instances
└── 1
├── mysql
└── www
```
The vichan container is by itself much less rigid.
Use `docker compose up --build` to start the docker compose.
Use `docker compose up --build -d php` to rebuild just the vichan container while the compose is running. Useful for development.

8
docker/nginx/Dockerfile Normal file
View File

@ -0,0 +1,8 @@
FROM nginx:1.25.3-alpine
COPY . /code
RUN adduser --system www-data \
&& adduser www-data www-data
CMD [ "nginx", "-g", "daemon off;" ]
EXPOSE 80

34
docker/nginx/nginx.conf Normal file
View File

@ -0,0 +1,34 @@
# This and proxy.conf are based on
# https://github.com/dead-guru/devichan/blob/master/nginx/nginx.conf
user www-data;
worker_processes auto;
error_log /dev/stdout warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Switch logging to console out to view via Docker
access_log /dev/stdout;
error_log /dev/stdout warn;
sendfile on;
keepalive_timeout 5;
gzip on;
gzip_http_version 1.0;
gzip_vary on;
gzip_comp_level 6;
gzip_types text/xml text/plain text/css application/xhtml+xml application/xml application/rss+xml application/atom_xml application/x-javascript application/x-httpd-php;
gzip_disable "MSIE [1-6]\.";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-available/*.conf;
}

40
docker/nginx/proxy.conf Normal file
View File

@ -0,0 +1,40 @@
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=czone:4m max_size=50m inactive=120m;
proxy_temp_path /var/tmp/nginx;
proxy_cache_key "$scheme://$host$request_uri";
map $http_forwarded_request_id $x_request_id {
"" $request_id;
default $http_forwarded_request_id;
}
map $http_forwarded_forwarded_host $forwardedhost {
"" $host;
default $http_forwarded_forwarded_host;
}
map $http_x_forwarded_proto $fcgi_https {
default "";
https on;
}
map $http_x_forwarded_proto $real_scheme {
default $scheme;
https https;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 172.18.0.0;
set_real_ip_from 192.168.0.0/24;
set_real_ip_from 127.0.0.0/8;
real_ip_recursive on;

66
docker/nginx/vichan.conf Normal file
View File

@ -0,0 +1,66 @@
upstream php-upstream {
server php:9000;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name vichan;
root /var/www/html;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.html index.php;
charset utf-8;
location ~ ^([^.\?]*[^\/])$ {
try_files $uri @addslash;
}
# Expire rules for static content
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|webp|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
log_not_found off;
add_header Cache-Control "public";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
expires 1y;
access_log off;
log_not_found off;
add_header Cache-Control "public";
}
location ~* \.(html)$ {
expires -1;
}
location @addslash {
return 301 $uri/;
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
client_max_body_size 2G;
location ~ \.php$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Request-Id $x_request_id;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Forwarded-Request-Id $x_request_id;
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name;
fastcgi_read_timeout 600;
include fastcgi_params;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
}

88
docker/php/Dockerfile Normal file
View File

@ -0,0 +1,88 @@
# Based on https://github.com/dead-guru/devichan/blob/master/php-fpm/Dockerfile
FROM composer:lts AS composer
FROM php:8.1-fpm-alpine
RUN apk add --no-cache \
zlib \
zlib-dev \
libpng \
libpng-dev \
libjpeg-turbo \
libjpeg-turbo-dev \
libwebp \
libwebp-dev \
libcurl \
curl-dev \
imagemagick \
graphicsmagick \
gifsicle \
ffmpeg \
bind-tools \
gettext \
gettext-dev \
icu-dev \
oniguruma \
oniguruma-dev \
libmcrypt \
libmcrypt-dev \
lz4-libs \
lz4-dev \
imagemagick-dev \
pcre-dev \
$PHPIZE_DEPS \
&& docker-php-ext-configure gd \
--with-webp=/usr/include/webp \
--with-jpeg=/usr/include \
&& docker-php-ext-install -j$(nproc) \
gd \
curl \
bcmath \
opcache \
pdo_mysql \
gettext \
intl \
mbstring \
&& pecl update-channels \
&& pecl install -o -f igbinary \
&& pecl install redis \
&& pecl install imagick \
$$ docker-php-ext-enable \
igbinary \
redis \
imagick \
&& apk del \
zlib-dev \
libpng-dev \
libjpeg-turbo-dev \
libwebp-dev \
curl-dev \
gettext-dev \
oniguruma-dev \
libmcrypt-dev \
lz4-dev \
imagemagick-dev \
pcre-dev \
$PHPIZE_DEPS \
&& rm -rf /var/cache/* \
&& rm -rf /tmp/pear
RUN rmdir /var/www/html \
&& install -d -m 744 -o www-data -g www-data /var/www \
&& install -d -m 700 -o www-data -g www-data /var/tmp/vichan \
&& install -d -m 700 -o www-data -g www-data /var/cache/gen-cache \
&& install -d -m 700 -o www-data -g www-data /var/cache/template-cache
# Copy the bootstrap script.
COPY ./docker/php/bootstrap.sh /usr/local/bin/bootstrap.sh
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
# Copy the actual project (use .dockerignore to exclude stuff).
COPY . /code
# Install the compose depedencies.
RUN cd /code && composer install
WORKDIR "/var/www"
CMD [ "bootstrap.sh" ]
EXPOSE 9000

View File

@ -0,0 +1,16 @@
# syntax = devthefuture/dockerfile-x
INCLUDE ./docker/php/Dockerfile
RUN apk add --no-cache \
linux-headers \
$PHPIZE_DEPS \
&& pecl update-channels \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& apk del \
linux-headers \
$PHPIZE_DEPS \
&& rm -rf /var/cache/*
ENV XDEBUG_OUT_DIR=/var/www/xdebug_out
CMD [ "bootstrap.sh" ]

87
docker/php/bootstrap.sh Executable file
View File

@ -0,0 +1,87 @@
#!/bin/sh
set -eu
function set_cfg() {
if [ -L "/var/www/inc/$1" ]; then
echo "INFO: Resetting $1"
rm "/var/www/inc/$1"
cp "/code/inc/$1" "/var/www/inc/$1"
chown www-data "/var/www/inc/$1"
chgrp www-data "/var/www/inc/$1"
chmod 600 "/var/www/inc/$1"
else
echo "INFO: Using existing $1"
fi
}
if ! mountpoint -q /var/www; then
echo "WARNING: '/var/www' is not a mountpoint. All the data will remain inside the container!"
fi
if [ ! -w /var/www ] ; then
echo "ERROR: '/var/www' is not writable. Closing."
exit 1
fi
if [ -z "${XDEBUG_OUT_DIR:-''}" ] ; then
echo "INFO: Initializing xdebug out directory at $XDEBUG_OUT_DIR"
mkdir -p "$XDEBUG_OUT_DIR"
chown www-data "$XDEBUG_OUT_DIR"
chgrp www-data "$XDEBUG_OUT_DIR"
chmod 755 "$XDEBUG_OUT_DIR"
fi
# Link the entrypoints from the exposed directory.
ln -nfs \
/code/tools/ \
/code/*.php \
/code/LICENSE.* \
/code/install.sql \
/var/www/
# Static files accessible from the webserver must be copied.
cp -ur /code/static /var/www/
cp -ur /code/stylesheets /var/www/
# Ensure correct permissions are set, since this might be bind mount.
chown www-data /var/www
chgrp www-data /var/www
# Initialize an empty robots.txt with the default if it doesn't exist.
touch /var/www/robots.txt
# Link the cache and tmp files directory.
ln -nfs /var/tmp/vichan /var/www/tmp
# Link the javascript directory.
ln -nfs /code/js /var/www/
# Link the html templates directory and it's cache.
ln -nfs /code/templates /var/www/
ln -nfs -T /var/cache/template-cache /var/www/templates/cache
chown -h www-data /var/www/templates/cache
chgrp -h www-data /var/www/templates/cache
# Link the generic cache.
ln -nfs -T /var/cache/gen-cache /var/www/tmp/cache
chown -h www-data /var/www/tmp/cache
chgrp -h www-data /var/www/tmp/cache
# Create the included files directory and link them
install -d -m 700 -o www-data -g www-data /var/www/inc
for file in /code/inc/*; do
file="${file##*/}"
if [ ! -e /var/www/inc/$file ]; then
ln -s /code/inc/$file /var/www/inc/
fi
done
# Copy an empty instance configuration if the file is a link (it was linked because it did not exist before).
set_cfg 'instance-config.php'
set_cfg 'secrets.php'
# Link the composer dependencies.
ln -nfs /code/vendor /var/www/
# Start the php-fpm server.
exec php-fpm

2
docker/php/jit.ini Normal file
View File

@ -0,0 +1,2 @@
opcache.jit_buffer_size=192M
opcache.jit=tracing

13
docker/php/www.conf Normal file
View File

@ -0,0 +1,13 @@
[www]
access.log = /proc/self/fd/2
; Ensure worker stdout and stderr are sent to the main error log.
catch_workers_output = yes
decorate_workers_output = no
user = www-data
group = www-data
listen = 127.0.0.1:9000
pm = static
pm.max_children = 16

View File

@ -0,0 +1,7 @@
zend_extension=xdebug
[xdebug]
xdebug.mode = profile
xdebug.start_with_request = start
error_reporting = E_ALL
xdebug.output_dir = /var/www/xdebug_out

View File

@ -0,0 +1,28 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
class ApcuCacheDriver implements CacheDriver {
public function get(string $key): mixed {
$success = false;
$ret = \apcu_fetch($key, $success);
if ($success === false) {
return null;
}
return $ret;
}
public function set(string $key, mixed $value, mixed $expires = false): void {
\apcu_store($key, $value, (int)$expires);
}
public function delete(string $key): void {
\apcu_delete($key);
}
public function flush(): void {
\apcu_clear_cache();
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* A simple process-wide PHP array.
*/
class ArrayCacheDriver implements CacheDriver {
private static $inner = [];
public function get(string $key) {
return isset(self::$inner[$key]) ? self::$inner[$key] : null;
}
public function set(string $key, $value, $expires = false): void {
self::$inner[$key] = $value;
}
public function delete(string $key): void {
unset(self::$inner[$key]);
}
public function flush(): void {
self::$inner = [];
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
interface CacheDriver {
/**
* Get the value of associated with the key.
*
* @param string $key The key of the value.
* @return mixed|null The value associated with the key, or null if there is none.
*/
public function get(string $key);
/**
* Set a key-value pair.
*
* @param string $key The key.
* @param mixed $value The value.
* @param int|false $expires After how many seconds the pair will expire. Use false or ignore this parameter to keep
* the value until it gets evicted to make space for more items. Some drivers will always
* ignore this parameter and store the pair until it's removed.
*/
public function set(string $key, $value, $expires = false);
/**
* Delete a key-value pair.
*
* @param string $key The key.
*/
public function delete(string $key);
/**
* Delete all the key-value pairs.
*/
public function flush();
}

View File

@ -0,0 +1,28 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* Log via the php function error_log.
*/
class ErrorLogLogDriver implements LogDriver {
use LogTrait;
private string $name;
private int $level;
public function __construct(string $name, int $level) {
$this->name = $name;
$this->level = $level;
}
public function log(int $level, string $message): void {
if ($level <= $this->level) {
$lv = $this->levelToString($level);
$line = "{$this->name} $lv: $message";
\error_log($line, 0, null, null);
}
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* Log to a file.
*/
class FileLogDriver implements LogDriver {
use LogTrait;
private string $name;
private int $level;
private mixed $fd;
public function __construct(string $name, int $level, string $file_path) {
/*
* error_log is slow as hell in it's 3rd mode, so use fopen + file locking instead.
* https://grobmeier.solutions/performance-ofnonblocking-write-to-files-via-php-21082009.html
*
* Whatever file appending is atomic is contentious:
* - There are no POSIX guarantees: https://stackoverflow.com/a/7237901
* - But linus suggested they are on linux, on some filesystems: https://web.archive.org/web/20151201111541/http://article.gmane.org/gmane.linux.kernel/43445
* - But it doesn't seem to be always the case: https://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/
*
* So we just use file locking to be sure.
*/
$this->fd = \fopen($file_path, 'a');
if ($this->fd === false) {
throw new \RuntimeException("Unable to open log file at $file_path");
}
$this->name = $name;
$this->level = $level;
// In some cases PHP does not run the destructor.
\register_shutdown_function([$this, 'close']);
}
public function __destruct() {
$this->close();
}
public function log(int $level, string $message): void {
if ($level <= $this->level) {
$lv = $this->levelToString($level);
$line = "{$this->name} $lv: $message\n";
\flock($this->fd, LOCK_EX);
\fwrite($this->fd, $line);
\fflush($this->fd);
\flock($this->fd, LOCK_UN);
}
}
public function close() {
\flock($this->fd, LOCK_UN);
\fclose($this->fd);
}
}

View File

@ -0,0 +1,155 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
class FsCacheDriver implements CacheDriver {
private string $prefix;
private string $base_path;
private mixed $lock_fd;
private int|false $collect_chance_den;
private function prepareKey(string $key): string {
$key = \str_replace('/', '::', $key);
$key = \str_replace("\0", '', $key);
return $this->prefix . $key;
}
private function sharedLockCache(): void {
\flock($this->lock_fd, LOCK_SH);
}
private function exclusiveLockCache(): void {
\flock($this->lock_fd, LOCK_EX);
}
private function unlockCache(): void {
\flock($this->lock_fd, LOCK_UN);
}
private function collectImpl(): int {
/*
* A read lock is ok, since it's alright if we delete expired items from under the feet of other processes, and
* no other process add new cache items or refresh existing ones.
*/
$files = \glob($this->base_path . $this->prefix . '*', \GLOB_NOSORT);
$count = 0;
foreach ($files as $file) {
$data = \file_get_contents($file);
$wrapped = \json_decode($data, true, 512, \JSON_THROW_ON_ERROR);
if ($wrapped['expires'] !== false && $wrapped['expires'] <= \time()) {
if (@\unlink($file)) {
$count++;
}
}
}
return $count;
}
private function maybeCollect(): void {
if ($this->collect_chance_den !== false && \mt_rand(0, $this->collect_chance_den - 1) === 0) {
$this->collect_chance_den = false; // Collect only once per instance (aka process).
$this->collectImpl();
}
}
public function __construct(string $prefix, string $base_path, string $lock_file, int|false $collect_chance_den) {
if ($base_path[\strlen($base_path) - 1] !== '/') {
$base_path = "$base_path/";
}
if (!\is_dir($base_path)) {
throw new \RuntimeException("$base_path is not a directory!");
}
if (!\is_writable($base_path)) {
throw new \RuntimeException("$base_path is not writable!");
}
$this->lock_fd = \fopen($base_path . $lock_file, 'w');
if ($this->lock_fd === false) {
throw new \RuntimeException('Unable to open the lock file!');
}
$this->prefix = $prefix;
$this->base_path = $base_path;
$this->collect_chance_den = $collect_chance_den;
}
public function __destruct() {
$this->close();
}
public function get(string $key): mixed {
$key = $this->prepareKey($key);
$this->sharedLockCache();
// Collect expired items first so if the target key is expired we shortcut to failure in the next lines.
$this->maybeCollect();
$fd = \fopen($this->base_path . $key, 'r');
if ($fd === false) {
$this->unlockCache();
return null;
}
$data = \stream_get_contents($fd);
\fclose($fd);
$this->unlockCache();
$wrapped = \json_decode($data, true, 512, \JSON_THROW_ON_ERROR);
if ($wrapped['expires'] !== false && $wrapped['expires'] <= \time()) {
// Already expired, leave it there since we already released the lock and pretend it doesn't exist.
return null;
} else {
return $wrapped['inner'];
}
}
public function set(string $key, mixed $value, mixed $expires = false): void {
$key = $this->prepareKey($key);
$wrapped = [
'expires' => $expires ? \time() + $expires : false,
'inner' => $value
];
$data = \json_encode($wrapped);
$this->exclusiveLockCache();
$this->maybeCollect();
\file_put_contents($this->base_path . $key, $data);
$this->unlockCache();
}
public function delete(string $key): void {
$key = $this->prepareKey($key);
$this->exclusiveLockCache();
@\unlink($this->base_path . $key);
$this->maybeCollect();
$this->unlockCache();
}
public function collect(): int {
$this->sharedLockCache();
$count = $this->collectImpl();
$this->unlockCache();
return $count;
}
public function flush(): void {
$this->exclusiveLockCache();
$files = \glob($this->base_path . $this->prefix . '*', \GLOB_NOSORT);
foreach ($files as $file) {
@\unlink($file);
}
$this->unlockCache();
}
public function close(): void {
\fclose($this->lock_fd);
}
}

View File

@ -0,0 +1,131 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* Honestly this is just a wrapper for cURL. Still useful to mock it and have an OOP API on PHP 7.
*/
class HttpDriver {
private $inner;
private int $timeout;
private int $max_file_size;
private function resetTowards(string $url, int $timeout): void {
\curl_reset($this->inner);
\curl_setopt_array($this->inner, [
\CURLOPT_URL => $url,
\CURLOPT_TIMEOUT => $timeout,
\CURLOPT_USERAGENT => 'Tinyboard',
\CURLOPT_PROTOCOLS => \CURLPROTO_HTTP | \CURLPROTO_HTTPS,
]);
}
public function __construct(int $timeout, int $max_file_size) {
$this->inner = \curl_init();
$this->timeout = $timeout;
$this->max_file_size = $max_file_size;
}
public function __destruct() {
\curl_close($this->inner);
}
/**
* Execute a GET request.
*
* @param string $endpoint Uri endpoint.
* @param ?array $data Optional GET parameters.
* @param int $timeout Optional request timeout in seconds. Use the default timeout if 0.
* @return string Returns the body of the response.
* @throws RuntimeException Throws on IO error.
*/
public function requestGet(string $endpoint, ?array $data, int $timeout = 0): string {
if (!empty($data)) {
$endpoint .= '?' . \http_build_query($data);
}
if ($timeout == 0) {
$timeout = $this->timeout;
}
$this->resetTowards($endpoint, $timeout);
\curl_setopt($this->inner, \CURLOPT_RETURNTRANSFER, true);
$ret = \curl_exec($this->inner);
if ($ret === false) {
throw new \RuntimeException(\curl_error($this->inner));
}
return $ret;
}
/**
* Execute a POST request.
*
* @param string $endpoint Uri endpoint.
* @param ?array $data Optional POST parameters.
* @param int $timeout Optional request timeout in seconds. Use the default timeout if 0.
* @return string Returns the body of the response.
* @throws RuntimeException Throws on IO error.
*/
public function requestPost(string $endpoint, ?array $data, int $timeout = 0): string {
if ($timeout == 0) {
$timeout = $this->timeout;
}
$this->resetTowards($endpoint, $timeout);
\curl_setopt($this->inner, \CURLOPT_POST, true);
if (!empty($data)) {
\curl_setopt($this->inner, \CURLOPT_POSTFIELDS, \http_build_query($data));
}
\curl_setopt($this->inner, \CURLOPT_RETURNTRANSFER, true);
$ret = \curl_exec($this->inner);
if ($ret === false) {
throw new \RuntimeException(\curl_error($this->inner));
}
return $ret;
}
/**
* Download the url's target with curl.
*
* @param string $url Url to the file to download.
* @param ?array $data Optional GET parameters.
* @param resource $fd File descriptor to save the content to.
* @param int $timeout Optional request timeout in seconds. Use the default timeout if 0.
* @return bool Returns true on success, false if the file was too large.
* @throws RuntimeException Throws on IO error.
*/
public function requestGetInto(string $endpoint, ?array $data, $fd, int $timeout = 0): bool {
if (!empty($data)) {
$endpoint .= '?' . \http_build_query($data);
}
if ($timeout == 0) {
$timeout = $this->timeout;
}
$this->resetTowards($endpoint, $timeout);
// Adapted from: https://stackoverflow.com/a/17642638
$opt = (\PHP_MAJOR_VERSION >= 8 && \PHP_MINOR_VERSION >= 2) ? \CURLOPT_XFERINFOFUNCTION : \CURLOPT_PROGRESSFUNCTION;
\curl_setopt_array($this->inner, [
\CURLOPT_NOPROGRESS => false,
$opt => fn($res, $next_dl, $dl, $next_up, $up) => (int)($dl <= $this->max_file_size),
\CURLOPT_FAILONERROR => true,
\CURLOPT_FOLLOWLOCATION => false,
\CURLOPT_FILE => $fd,
\CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
]);
$ret = \curl_exec($this->inner);
if ($ret === false) {
if (\curl_errno($this->inner) === CURLE_ABORTED_BY_CALLBACK) {
return false;
}
throw new \RuntimeException(\curl_error($this->inner));
}
return true;
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
interface LogDriver {
public const EMERG = \LOG_EMERG;
public const ERROR = \LOG_ERR;
public const WARNING = \LOG_WARNING;
public const NOTICE = \LOG_NOTICE;
public const INFO = \LOG_INFO;
public const DEBUG = \LOG_DEBUG;
/**
* Log a message if the level of relevancy is at least the minimum.
*
* @param int $level Message level. Use Log interface constants.
* @param string $message The message to log.
*/
public function log(int $level, string $message): void;
}

View File

@ -0,0 +1,26 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
trait LogTrait {
public static function levelToString(int $level): string {
switch ($level) {
case LogDriver::EMERG:
return 'EMERG';
case LogDriver::ERROR:
return 'ERROR';
case LogDriver::WARNING:
return 'WARNING';
case LogDriver::NOTICE:
return 'NOTICE';
case LogDriver::INFO:
return 'INFO';
case LogDriver::DEBUG:
return 'DEBUG';
default:
throw new \InvalidArgumentException('Not a logging level');
}
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
class MemcachedCacheDriver implements CacheDriver {
private \Memcached $inner;
public function __construct(string $prefix, string $memcached_server) {
$this->inner = new \Memcached();
if (!$this->inner->setOption(\Memcached::OPT_BINARY_PROTOCOL, true)) {
throw new \RuntimeException('Unable to set the memcached protocol!');
}
if (!$this->inner->setOption(\Memcached::OPT_PREFIX_KEY, $prefix)) {
throw new \RuntimeException('Unable to set the memcached prefix!');
}
if (!$this->inner->addServers($memcached_server)) {
throw new \RuntimeException('Unable to add the memcached server!');
}
}
public function get(string $key): mixed {
$ret = $this->inner->get($key);
// If the returned value is false but the retrival was a success, then the value stored was a boolean false.
if ($ret === false && $this->inner->getResultCode() !== \Memcached::RES_SUCCESS) {
return null;
}
return $ret;
}
public function set(string $key, mixed $value, mixed $expires = false): void {
$this->inner->set($key, $value, (int)$expires);
}
public function delete(string $key): void {
$this->inner->delete($key);
}
public function flush(): void {
$this->inner->flush();
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* No-op cache. Useful for testing.
*/
class NoneCacheDriver implements CacheDriver {
public function get(string $key): mixed {
return null;
}
public function set(string $key, mixed $value, mixed $expires = false): void {
// No-op.
}
public function delete(string $key): void {
// No-op.
}
public function flush(): void {
// No-op.
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
class RedisCacheDriver implements CacheDriver {
private string $prefix;
private \Redis $inner;
public function __construct(string $prefix, string $host, int $port, ?string $password, string $database) {
$this->inner = new \Redis();
$this->inner->connect($host, $port);
if ($password) {
$this->inner->auth($password);
}
if (!$this->inner->select($database)) {
throw new \RuntimeException('Unable to connect to Redis!');
}
$$this->prefix = $prefix;
}
public function get(string $key): mixed {
$ret = $this->inner->get($this->prefix . $key);
if ($ret === false) {
return null;
}
return \json_decode($ret, true);
}
public function set(string $key, mixed $value, mixed $expires = false): void {
if ($expires === false) {
$this->inner->set($this->prefix . $key, \json_encode($value));
} else {
$expires = $expires * 1000; // Seconds to milliseconds.
$this->inner->setex($this->prefix . $key, $expires, \json_encode($value));
}
}
public function delete(string $key): void {
$this->inner->del($this->prefix . $key);
}
public function flush(): void {
$this->inner->flushDB();
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* Log to php's standard error file stream.
*/
class StderrLogDriver implements LogDriver {
use LogTrait;
private string $name;
private int $level;
public function __construct(string $name, int $level) {
$this->name = $name;
$this->level = $level;
}
public function log(int $level, string $message): void {
if ($level <= $this->level) {
$lv = $this->levelToString($level);
\fwrite(\STDERR, "{$this->name} $lv: $message\n");
}
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Vichan\Data\Driver;
defined('TINYBOARD') or exit;
/**
* Log to syslog.
*/
class SyslogLogDriver implements LogDriver {
private int $level;
public function __construct(string $name, int $level, bool $print_stderr) {
$flags = \LOG_ODELAY;
if ($print_stderr) {
$flags |= \LOG_PERROR;
}
if (!\openlog($name, $flags, \LOG_USER)) {
throw new \RuntimeException('Unable to open syslog');
}
$this->level = $level;
}
public function log(int $level, string $message): void {
if ($level <= $this->level) {
if (isset($_SERVER['REMOTE_ADDR'], $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'])) {
// CGI
\syslog($level, "$message - client: {$_SERVER['REMOTE_ADDR']}, request: \"{$_SERVER['REQUEST_METHOD']} {$_SERVER['REQUEST_URI']}\"");
} else {
\syslog($level, $message);
}
}
}
}

View File

@ -1,282 +1,5 @@
<?php
/*
* Copyright (c) 2010-2013 Tinyboard Development Group
* Anti-bot.php has been deprecated and removed due to its functions not being necessary and being easily bypassable, by both customized and uncustomized spambots.
*/
defined('TINYBOARD') or exit;
$hidden_inputs_twig = array();
class AntiBot {
public $salt, $inputs = array(), $index = 0;
public static function randomString($length, $uppercase = false, $special_chars = false, $unicode_chars = false) {
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
if ($uppercase)
$chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if ($special_chars)
$chars .= ' ~!@#$%^&*()_+,./;\'[]\\{}|:<>?=-` ';
if ($unicode_chars) {
$len = strlen($chars) / 10;
for ($n = 0; $n < $len; $n++)
$chars .= mb_convert_encoding('&#' . mt_rand(0x2600, 0x26FF) . ';', 'UTF-8', 'HTML-ENTITIES');
}
$chars = preg_split('//u', $chars, -1, PREG_SPLIT_NO_EMPTY);
$ch = array();
// fill up $ch until we reach $length
while (count($ch) < $length) {
$n = $length - count($ch);
$keys = array_rand($chars, $n > count($chars) ? count($chars) : $n);
if ($n == 1) {
$ch[] = $chars[$keys];
break;
}
shuffle($keys);
foreach ($keys as $key)
$ch[] = $chars[$key];
}
$chars = $ch;
return implode('', $chars);
}
public static function make_confusing($string) {
$chars = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
foreach ($chars as &$c) {
if (mt_rand(0, 3) != 0)
$c = utf8tohtml($c);
else
$c = mb_encode_numericentity($c, array(0, 0xffff, 0, 0xffff), 'UTF-8');
}
return implode('', $chars);
}
public function __construct(array $salt = array()) {
global $config;
if (!empty($salt)) {
// create a salted hash of the "extra salt"
$this->salt = implode(':', $salt);
} else {
$this->salt = '';
}
shuffle($config['spam']['hidden_input_names']);
$input_count = mt_rand($config['spam']['hidden_inputs_min'], $config['spam']['hidden_inputs_max']);
$hidden_input_names_x = 0;
for ($x = 0; $x < $input_count ; $x++) {
if ($hidden_input_names_x === false || mt_rand(0, 2) == 0) {
// Use an obscure name
$name = $this->randomString(mt_rand(10, 40), false, false, $config['spam']['unicode']);
} else {
// Use a pre-defined confusing name
$name = $config['spam']['hidden_input_names'][$hidden_input_names_x++];
if ($hidden_input_names_x >= count($config['spam']['hidden_input_names']))
$hidden_input_names_x = false;
}
if (mt_rand(0, 2) == 0) {
// Value must be null
$this->inputs[$name] = '';
} elseif (mt_rand(0, 4) == 0) {
// Numeric value
$this->inputs[$name] = (string)mt_rand(0, 100000);
} else {
// Obscure value
$this->inputs[$name] = $this->randomString(mt_rand(5, 100), true, true, $config['spam']['unicode']);
}
}
}
public static function space() {
if (mt_rand(0, 3) != 0)
return ' ';
return str_repeat(' ', mt_rand(1, 3));
}
public function html($count = false) {
global $config;
$elements = array(
'<input type="hidden" name="%name%" value="%value%">',
'<input type="hidden" value="%value%" name="%name%">',
'<input name="%name%" value="%value%" type="hidden">',
'<input value="%value%" name="%name%" type="hidden">',
'<input style="display:none" type="text" name="%name%" value="%value%">',
'<input style="display:none" type="text" value="%value%" name="%name%">',
'<span style="display:none"><input type="text" name="%name%" value="%value%"></span>',
'<div style="display:none"><input type="text" name="%name%" value="%value%"></div>',
'<div style="display:none"><input type="text" name="%name%" value="%value%"></div>',
'<textarea style="display:none" name="%name%">%value%</textarea>',
'<textarea name="%name%" style="display:none">%value%</textarea>'
);
$html = '';
if ($count === false) {
$count = mt_rand(1, abs(count($this->inputs) / 15) + 1);
}
if ($count === true) {
// all elements
$inputs = array_slice($this->inputs, $this->index);
} else {
$inputs = array_slice($this->inputs, $this->index, $count);
}
$this->index += count($inputs);
foreach ($inputs as $name => $value) {
$element = false;
while (!$element) {
$element = $elements[array_rand($elements)];
$element = str_replace(' ', self::space(), $element);
if (mt_rand(0, 5) == 0)
$element = str_replace('>', self::space() . '>', $element);
if (strpos($element, 'textarea') !== false && $value == '') {
// There have been some issues with mobile web browsers and empty <textarea>'s.
$element = false;
}
}
$element = str_replace('%name%', utf8tohtml($name), $element);
if (mt_rand(0, 2) == 0)
$value = $this->make_confusing($value);
else
$value = utf8tohtml($value);
if (strpos($element, 'textarea') === false)
$value = str_replace('"', '&quot;', $value);
$element = str_replace('%value%', $value, $element);
$html .= $element;
}
return $html;
}
public function reset() {
$this->index = 0;
}
public function hash() {
global $config;
// This is the tricky part: create a hash to validate it after
// First, sort the keys in alphabetical order (A-Z)
$inputs = $this->inputs;
ksort($inputs);
$hash = '';
// Iterate through each input
foreach ($inputs as $name => $value) {
$hash .= $name . '=' . $value;
}
// Add a salt to the hash
$hash .= $config['cookies']['salt'];
// Use SHA1 for the hash
return sha1($hash . $this->salt);
}
}
function _create_antibot($board, $thread) {
global $config, $purged_old_antispam;
$antibot = new AntiBot(array($board, $thread));
if (!isset($purged_old_antispam)) {
$purged_old_antispam = true;
query('DELETE FROM ``antispam`` WHERE `expires` < UNIX_TIMESTAMP()') or error(db_error());
}
if ($thread)
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` = :thread AND `expires` IS NULL');
else
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` IS NULL AND `expires` IS NULL');
$query->bindValue(':board', $board);
if ($thread)
$query->bindValue(':thread', $thread);
$query->bindValue(':expires', $config['spam']['hidden_inputs_expire']);
$query->execute() or error(db_error($query));
$query = prepare('INSERT INTO ``antispam`` VALUES (:board, :thread, :hash, UNIX_TIMESTAMP(), NULL, 0)');
$query->bindValue(':board', $board);
$query->bindValue(':thread', $thread);
$query->bindValue(':hash', $antibot->hash());
$query->execute() or error(db_error($query));
return $antibot;
}
function checkSpam(array $extra_salt = array()) {
global $config, $pdo;
if (!isset($_POST['hash']))
return true;
$hash = $_POST['hash'];
if (!empty($extra_salt)) {
// create a salted hash of the "extra salt"
$extra_salt = implode(':', $extra_salt);
} else {
$extra_salt = '';
}
// Reconsturct the $inputs array
$inputs = array();
foreach ($_POST as $name => $value) {
if (in_array($name, $config['spam']['valid_inputs']))
continue;
$inputs[$name] = $value;
}
// Sort the inputs in alphabetical order (A-Z)
ksort($inputs);
$_hash = '';
// Iterate through each input
foreach ($inputs as $name => $value) {
$_hash .= $name . '=' . $value;
}
// Add a salt to the hash
$_hash .= $config['cookies']['salt'];
// Use SHA1 for the hash
$_hash = sha1($_hash . $extra_salt);
if ($hash != $_hash)
return true;
$query = prepare('SELECT `passed` FROM ``antispam`` WHERE `hash` = :hash');
$query->bindValue(':hash', $hash);
$query->execute() or error(db_error($query));
if ((($passed = $query->fetchColumn(0)) === false) || ($passed > $config['spam']['hidden_inputs_max_pass'])) {
// there was no database entry for this hash. most likely expired.
return true;
}
return $hash;
}
function incrementSpamHash($hash) {
$query = prepare('UPDATE ``antispam`` SET `passed` = `passed` + 1 WHERE `hash` = :hash');
$query->bindValue(':hash', $hash);
$query->execute() or error(db_error($query));
}

View File

@ -9,49 +9,12 @@ defined('TINYBOARD') or exit;
* Class for generating json API compatible with 4chan API
*/
class Api {
function __construct(){
global $config;
/**
* Translation from local fields to fields in 4chan-style API
*/
$this->config = $config;
private bool $show_filename;
private bool $hide_email;
private bool $country_flags;
private array $postFields;
$this->postFields = array(
'id' => 'no',
'thread' => 'resto',
'subject' => 'sub',
'body' => 'com',
'email' => 'email',
'name' => 'name',
'trip' => 'trip',
'capcode' => 'capcode',
'time' => 'time',
'thumbheight' => 'tn_w',
'thumbwidth' => 'tn_h',
'fileheight' => 'w',
'filewidth' => 'h',
'filesize' => 'fsize',
'filename' => 'filename',
'omitted' => 'omitted_posts',
'omitted_images' => 'omitted_images',
'replies' => 'replies',
'images' => 'images',
'sticky' => 'sticky',
'locked' => 'locked',
'bump' => 'last_modified',
);
$this->threadsPageFields = array(
'id' => 'no',
'bump' => 'last_modified'
);
if (isset($config['api']['extra_fields']) && gettype($config['api']['extra_fields']) == 'array'){
$this->postFields = array_merge($this->postFields, $config['api']['extra_fields']);
}
}
private static $ints = array(
private const INTS = [
'no' => 1,
'resto' => 1,
'time' => 1,
@ -62,38 +25,110 @@ class Api {
'fsize' => 1,
'omitted_posts' => 1,
'omitted_images' => 1,
'replies' => 1,
'images' => 1,
'sticky' => 1,
'locked' => 1,
'last_modified' => 1
);
];
private function translatePost($post, $threadsPage = false) {
$apiPost = array();
$fields = $threadsPage ? $this->threadsPageFields : $this->postFields;
private const THREADS_PAGE_FIELDS = [
'id' => 'no',
'bump' => 'last_modified'
];
private const FILE_FIELDS = [
'thumbheight' => 'tn_h',
'thumbwidth' => 'tn_w',
'height' => 'h',
'width' => 'w',
'size' => 'fsize'
];
public function __construct(bool $show_filename, bool $hide_email, bool $country_flags) {
// Translation from local fields to fields in 4chan-style API
$this->show_filename = $show_filename;
$this->hide_email = $hide_email;
$this->country_flags = $country_flags;
$this->postFields = [
'id' => 'no',
'thread' => 'resto',
'subject' => 'sub',
'body' => 'com',
'email' => 'email',
'name' => 'name',
'trip' => 'trip',
'capcode' => 'capcode',
'time' => 'time',
'omitted' => 'omitted_posts',
'omitted_images' => 'omitted_images',
'replies' => 'replies',
'images' => 'images',
'sticky' => 'sticky',
'locked' => 'locked',
'cycle' => 'cyclical',
'bump' => 'last_modified',
'embed' => 'embed',
];
if (isset($config['api']['extra_fields']) && gettype($config['api']['extra_fields']) == 'array'){
$this->postFields = array_merge($this->postFields, $config['api']['extra_fields']);
}
}
private function translateFields($fields, $object, &$apiPost) {
foreach ($fields as $local => $translated) {
if (!isset($post->$local))
if (!isset($object->$local)) {
continue;
}
$toInt = isset(self::$ints[$translated]);
$val = $post->$local;
$toInt = isset(self::INTS[$translated]);
$val = $object->$local;
if ($this->hide_email && $local === 'email') {
$val = '';
}
if ($val !== null && $val !== '') {
$apiPost[$translated] = $toInt ? (int) $val : $val;
}
}
}
if ($threadsPage) return $apiPost;
private function translateFile($file, $post, &$apiPost) {
$this->translateFields(self::FILE_FIELDS, $file, $apiPost);
$dotPos = strrpos($file->file, '.');
$apiPost['ext'] = substr($file->file, $dotPos);
$apiPost['tim'] = substr($file->file, 0, $dotPos);
if (isset($post->filename)) {
$dotPos = strrpos($post->filename, '.');
$apiPost['filename'] = substr($post->filename, 0, $dotPos);
$apiPost['ext'] = substr($post->filename, $dotPos);
$dotPos = strrpos($post->file, '.');
$apiPost['tim'] = substr($post->file, 0, $dotPos);
if ($this->show_filename) {
$apiPost['filename'] = @substr($file->name, 0, strrpos($file->name, '.'));
} else {
$apiPost['filename'] = substr($file->file, 0, $dotPos);
}
if (isset ($file->hash) && $file->hash) {
$apiPost['md5'] = base64_encode(hex2bin($file->hash));
} elseif (isset ($post->filehash) && $post->filehash) {
$apiPost['md5'] = base64_encode(hex2bin($post->filehash));
}
}
private function translatePost($post, bool $threadsPage = false) {
global $config, $board;
$apiPost = [];
$fields = $threadsPage ? self::THREADS_PAGE_FIELDS : $this->postFields;
$this->translateFields($fields, $post, $apiPost);
if (isset($config['poster_ids']) && $config['poster_ids']) {
$apiPost['id'] = poster_id($post->ip, $post->thread ?? $post->id);
}
if ($threadsPage) {
return $apiPost;
}
// Handle country field
if (isset($post->body_nomarkup) && $this->config['country_flags']) {
if (isset($post->body_nomarkup) && $this->country_flags) {
$modifiers = extract_modifiers($post->body_nomarkup);
if (isset($modifiers['flag']) && isset($modifiers['flag alt']) && preg_match('/^[a-z]{2}$/', $modifiers['flag'])) {
$country = strtoupper($modifiers['flag']);
@ -104,11 +139,37 @@ class Api {
}
}
if ($config['slugify'] && !$post->thread) {
$apiPost['semantic_url'] = $post->slug;
}
// Handle files
// Note: 4chan only supports one file, so only the first file is taken into account for 4chan-compatible API.
if (isset($post->files) && $post->files && !$threadsPage) {
$file = $post->files[0];
$this->translateFile($file, $post, $apiPost);
if (sizeof($post->files) > 1) {
$extra_files = [];
foreach ($post->files as $i => $f) {
if ($i == 0) {
continue;
}
$extra_file = [];
$this->translateFile($f, $post, $extra_file);
$extra_files[] = $extra_file;
}
$apiPost['extra_files'] = $extra_files;
}
}
return $apiPost;
}
function translateThread(Thread $thread, $threadsPage = false) {
$apiPosts = array();
public function translateThread(Thread $thread, bool $threadsPage = false) {
$apiPosts = [];
$op = $this->translatePost($thread, $threadsPage);
if (!$threadsPage) $op['resto'] = 0;
$apiPosts['posts'][] = $op;
@ -120,16 +181,16 @@ class Api {
return $apiPosts;
}
function translatePage(array $threads) {
$apiPage = array();
public function translatePage(array $threads) {
$apiPage = [];
foreach ($threads as $thread) {
$apiPage['threads'][] = $this->translateThread($thread);
}
return $apiPage;
}
function translateCatalogPage(array $threads, $threadsPage = false) {
$apiPage = array();
public function translateCatalogPage(array $threads, bool $threadsPage = false) {
$apiPage = [];
foreach ($threads as $thread) {
$ts = $this->translateThread($thread, $threadsPage);
$apiPage['threads'][] = current($ts['posts']);
@ -137,8 +198,8 @@ class Api {
return $apiPage;
}
function translateCatalog($catalog, $threadsPage = false) {
$apiCatalog = array();
public function translateCatalog($catalog, bool $threadsPage = false) {
$apiCatalog = [];
foreach ($catalog as $page => $threads) {
$apiPage = $this->translateCatalogPage($threads, $threadsPage);
$apiPage['page'] = $page;

View File

@ -1,12 +1,163 @@
<?php
require 'inc/lib/IP/Lifo/IP/IP.php';
require 'inc/lib/IP/Lifo/IP/BC.php';
require 'inc/lib/IP/Lifo/IP/CIDR.php';
use Vichan\Functions\Format;
use Lifo\IP\CIDR;
class Bans {
static private function shouldDelete(array $ban, bool $require_ban_view) {
return $ban['expires'] && ($ban['seen'] || !$require_ban_view) && $ban['expires'] < time();
}
static private function deleteBans(array $ban_ids) {
$len = count($ban_ids);
if ($len === 1) {
$query = prepare('DELETE FROM ``bans`` WHERE `id` = :id');
$query->bindValue(':id', $ban_ids[0], PDO::PARAM_INT);
$query->execute() or error(db_error());
Vichan\Functions\Theme\rebuild_themes('bans');
} elseif ($len >= 1) {
// Build the query.
$query = 'DELETE FROM ``bans`` WHERE `id` IN (';
for ($i = 0; $i < $len; $i++) {
$query .= ":id{$i},";
}
// Substitute the last comma with a parenthesis.
substr_replace($query, ')', strlen($query) - 1);
// Bind the params
$query = prepare($query);
for ($i = 0; $i < $len; $i++) {
$query->bindValue(":id{$i}", (int)$ban_ids[$i], PDO::PARAM_INT);
}
$query->execute() or error(db_error());
Vichan\Functions\Theme\rebuild_themes('bans');
}
}
static private function findSingleAutoGc(string $ip, int $ban_id, bool $require_ban_view) {
// Use OR in the query to also garbage collect bans.
$query = prepare(
'SELECT ``bans``.* FROM ``bans``
WHERE ((`ipstart` = :ip OR (:ip >= `ipstart` AND :ip <= `ipend`)) OR (``bans``.id = :id))
ORDER BY `expires` IS NULL, `expires` DESC'
);
$query->bindValue(':id', $ban_id);
$query->bindValue(':ip', inet_pton($ip));
$query->execute() or error(db_error($query));
$found_ban = null;
$to_delete_list = [];
while ($ban = $query->fetch(PDO::FETCH_ASSOC)) {
if (self::shouldDelete($ban, $require_ban_view)) {
$to_delete_list[] = $ban['id'];
} elseif ($ban['id'] === $ban_id) {
if ($ban['post']) {
$ban['post'] = json_decode($ban['post'], true);
}
$ban['mask'] = self::range_to_string([$ban['ipstart'], $ban['ipend']]);
$found_ban = $ban;
}
}
self::deleteBans($to_delete_list);
return $found_ban;
}
static private function findSingleNoGc(int $ban_id) {
$query = prepare(
'SELECT ``bans``.* FROM ``bans``
WHERE ``bans``.id = :id
ORDER BY `expires` IS NULL, `expires` DESC
LIMIT 1'
);
$query->bindValue(':id', $ban_id);
$query->execute() or error(db_error($query));
$ret = $query->fetch(PDO::FETCH_ASSOC);
if ($query->rowCount() == 0) {
return null;
} else {
if ($ret['post']) {
$ret['post'] = json_decode($ret['post'], true);
}
$ret['mask'] = self::range_to_string([$ret['ipstart'], $ret['ipend']]);
return $ret;
}
}
static private function findAutoGc(?string $ip, $board, bool $get_mod_info, bool $require_ban_view, ?int $ban_id): array {
$query = prepare('SELECT ``bans``.*' . ($get_mod_info ? ', `username`' : '') . ' FROM ``bans``
' . ($get_mod_info ? 'LEFT JOIN ``mods`` ON ``mods``.`id` = `creator`' : '') . '
WHERE
(' . ($board !== false ? '(`board` IS NULL OR `board` = :board) AND' : '') . '
(`ipstart` = :ip OR (:ip >= `ipstart` AND :ip <= `ipend`)) OR (``bans``.id = :id))
ORDER BY `expires` IS NULL, `expires` DESC');
if ($board !== false) {
$query->bindValue(':board', $board, PDO::PARAM_STR);
}
$query->bindValue(':id', $ban_id);
$query->bindValue(':ip', inet_pton($ip));
$query->execute() or error(db_error($query));
$ban_list = [];
$to_delete_list = [];
while ($ban = $query->fetch(PDO::FETCH_ASSOC)) {
if (self::shouldDelete($ban, $require_ban_view)) {
$to_delete_list[] = $ban['id'];
} else {
if ($ban['post']) {
$ban['post'] = json_decode($ban['post'], true);
}
$ban['mask'] = self::range_to_string([$ban['ipstart'], $ban['ipend']]);
$ban_list[] = $ban;
}
}
self::deleteBans($to_delete_list);
return $ban_list;
}
static private function findNoGc(?string $ip, string $board, bool $get_mod_info, ?int $ban_id): array {
$query = prepare('SELECT ``bans``.*' . ($get_mod_info ? ', `username`' : '') . ' FROM ``bans``
' . ($get_mod_info ? 'LEFT JOIN ``mods`` ON ``mods``.`id` = `creator`' : '') . '
WHERE
(' . ($board !== false ? '(`board` IS NULL OR `board` = :board) AND' : '') . '
(`ipstart` = :ip OR (:ip >= `ipstart` AND :ip <= `ipend`)) OR (``bans``.id = :id))
AND (`expires` IS NULL OR `expires` >= :curr_time)
ORDER BY `expires` IS NULL, `expires` DESC');
if ($board !== false) {
$query->bindValue(':board', $board, PDO::PARAM_STR);
}
$query->bindValue(':id', $ban_id);
$query->bindValue(':ip', inet_pton($ip));
$query->bindValue(':curr_time', time());
$query->execute() or error(db_error($query));
$ban_list = $query->fetchAll(PDO::FETCH_ASSOC);
array_walk($ban_list, function (&$ban, $_index) {
if ($ban['post']) {
$ban['post'] = json_decode($ban['post'], true);
}
$ban['mask'] = self::range_to_string([$ban['ipstart'], $ban['ipend']]);
});
return $ban_list;
}
static public function range_to_string($mask) {
list($ipstart, $ipend) = $mask;
@ -30,7 +181,7 @@ class Bans {
$cidr = new CIDR($mask);
$range = $cidr->getRange();
return array(inet_pton($range[0]), inet_pton($range[1]));
return [ inet_pton($range[0]), inet_pton($range[1]) ];
}
public static function parse_time($str) {
@ -47,31 +198,31 @@ class Bans {
if (isset($matches[2])) {
// Years
$expire += $matches[2]*60*60*24*365;
$expire += (int)$matches[2]*60*60*24*365;
}
if (isset($matches[4])) {
// Months
$expire += $matches[4]*60*60*24*30;
$expire += (int)$matches[4]*60*60*24*30;
}
if (isset($matches[6])) {
// Weeks
$expire += $matches[6]*60*60*24*7;
$expire += (int)$matches[6]*60*60*24*7;
}
if (isset($matches[8])) {
// Days
$expire += $matches[8]*60*60*24;
$expire += (int)$matches[8]*60*60*24;
}
if (isset($matches[10])) {
// Hours
$expire += $matches[10]*60*60;
$expire += (int)$matches[10]*60*60;
}
if (isset($matches[12])) {
// Minutes
$expire += $matches[12]*60;
$expire += (int)$matches[12]*60;
}
if (isset($matches[14])) {
// Seconds
$expire += $matches[14];
$expire += (int)$matches[14];
}
return time() + $expire;
@ -114,90 +265,135 @@ class Bans {
return false;
}
return array($ipstart, $ipend);
return [$ipstart, $ipend];
}
static public function find($ip, $board = false, $get_mod_info = false) {
static public function findSingle(string $ip, int $ban_id, bool $require_ban_view, bool $auto_gc) {
if ($auto_gc) {
return self::findSingleAutoGc($ip, $ban_id, $require_ban_view);
} else {
return self::findSingleNoGc($ban_id);
}
}
static public function find(?string $ip, $board = false, bool $get_mod_info = false, ?int $ban_id = null, bool $auto_gc = true) {
global $config;
$query = prepare('SELECT ``bans``.*' . ($get_mod_info ? ', `username`' : '') . ' FROM ``bans``
' . ($get_mod_info ? 'LEFT JOIN ``mods`` ON ``mods``.`id` = `creator`' : '') . '
WHERE
(' . ($board ? '(`board` IS NULL OR `board` = :board) AND' : '') . '
(`ipstart` = :ip OR (:ip >= `ipstart` AND :ip <= `ipend`)))
ORDER BY `expires` IS NULL, `expires` DESC');
if ($auto_gc) {
return self::findAutoGc($ip, $board, $get_mod_info, $config['require_ban_view'], $ban_id);
} else {
return self::findNoGc($ip, $board, $get_mod_info, $ban_id);
}
}
if ($board)
$query->bindValue(':board', $board);
static public function stream_json($out = false, $filter_ips = false, $filter_staff = false, $board_access = false) {
$query = query("SELECT ``bans``.*, `username` FROM ``bans``
LEFT JOIN ``mods`` ON ``mods``.`id` = `creator`
ORDER BY `created` DESC") or error(db_error());
$bans = $query->fetchAll(PDO::FETCH_ASSOC);
$query->bindValue(':ip', inet_pton($ip));
$query->execute() or error(db_error($query));
if ($board_access && $board_access[0] == '*') $board_access = false;
$ban_list = array();
$out ? fputs($out, "[") : print("[");
while ($ban = $query->fetch(PDO::FETCH_ASSOC)) {
if ($ban['expires'] && ($ban['seen'] || !$config['require_ban_view']) && $ban['expires'] < time()) {
self::delete($ban['id']);
} else {
if ($ban['post'])
$ban['post'] = json_decode($ban['post'], true);
$ban['mask'] = self::range_to_string(array($ban['ipstart'], $ban['ipend']));
$ban_list[] = $ban;
$end = end($bans);
foreach ($bans as &$ban) {
$ban['mask'] = self::range_to_string([$ban['ipstart'], $ban['ipend']]);
if ($ban['post']) {
$post = json_decode($ban['post']);
$ban['message'] = isset($post->body) ? $post->body : 0;
}
unset($ban['ipstart'], $ban['ipend'], $ban['post'], $ban['creator']);
if ($board_access === false || in_array ($ban['board'], $board_access)) {
$ban['access'] = true;
}
if (filter_var($uncloaked_mask, FILTER_VALIDATE_IP) !== false) {
$ban['single_addr'] = true;
}
if ($filter_staff || ($board_access !== false && !in_array($ban['board'], $board_access))) {
$ban['username'] = '?';
}
if ($filter_ips || ($board_access !== false && !in_array($ban['board'], $board_access))) {
@list($ban['mask'], $subnet) = explode("/", $ban['mask']);
$ban['mask'] = preg_split("/[\.:]/", $ban['mask']);
$ban['mask'] = array_slice($ban['mask'], 0, 2);
$ban['mask'] = implode(".", $ban['mask']);
$ban['mask'] .= ".x.x";
if (isset ($subnet)) {
$ban['mask'] .= "/$subnet";
}
$ban['masked'] = true;
}
$json = json_encode($ban);
$out ? fputs($out, $json) : print($json);
if ($ban['id'] != $end['id']) {
$out ? fputs($out, ",") : print(",");
}
}
return $ban_list;
}
$out ? fputs($out, "]") : print("]");
static public function list_all($offset = 0, $limit = 9001) {
$offset = (int)$offset;
$limit = (int)$limit;
$query = query("SELECT ``bans``.*, `username` FROM ``bans``
LEFT JOIN ``mods`` ON ``mods``.`id` = `creator`
ORDER BY `created` DESC LIMIT $offset, $limit") or error(db_error());
$bans = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($bans as &$ban) {
$ban['mask'] = self::range_to_string(array($ban['ipstart'], $ban['ipend']));
}
return $bans;
}
static public function count() {
$query = query("SELECT COUNT(*) FROM ``bans``") or error(db_error());
return (int)$query->fetchColumn();
}
static public function seen($ban_id) {
$query = query("UPDATE ``bans`` SET `seen` = 1 WHERE `id` = " . (int)$ban_id) or error(db_error());
Vichan\Functions\Theme\rebuild_themes('bans');
}
static public function purge() {
$query = query("DELETE FROM ``bans`` WHERE `expires` IS NOT NULL AND `expires` < " . time() . " AND `seen` = 1") or error(db_error());
static public function purge($require_seen, $moratorium) {
if ($require_seen) {
$query = prepare("DELETE FROM ``bans`` WHERE `expires` IS NOT NULL AND `expires` + :moratorium < :curr_time AND `seen` = 1");
} else {
$query = prepare("DELETE FROM ``bans`` WHERE `expires` IS NOT NULL AND `expires` + :moratorium < :curr_time");
}
$query->bindValue(':moratorium', $moratorium);
$query->bindValue(':curr_time', time());
$query->execute() or error(db_error($query));
$affected = $query->rowCount();
if ($affected > 0) {
Vichan\Functions\Theme\rebuild_themes('bans');
}
return $affected;
}
static public function delete($ban_id, $modlog = false) {
static public function delete($ban_id, $modlog = false, $boards = false, $dont_rebuild = false) {
global $config;
if ($boards && $boards[0] == '*') $boards = false;
if ($modlog) {
$query = query("SELECT `ipstart`, `ipend` FROM ``bans`` WHERE `id` = " . (int)$ban_id) or error(db_error());
$query = query("SELECT `ipstart`, `ipend`, `board` FROM ``bans`` WHERE `id` = " . (int)$ban_id) or error(db_error());
if (!$ban = $query->fetch(PDO::FETCH_ASSOC)) {
// Ban doesn't exist
return false;
}
$mask = self::range_to_string(array($ban['ipstart'], $ban['ipend']));
if ($boards !== false && !in_array($ban['board'], $boards))
error($config['error']['noaccess']);
$mask = self::range_to_string([$ban['ipstart'], $ban['ipend']]);
modLog("Removed ban #{$ban_id} for " .
(filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/$mask\">$mask</a>" : $mask));
(filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/$cloaked_mask\">$cloaked_mask</a>" : $cloaked_mask));
}
query("DELETE FROM ``bans`` WHERE `id` = " . (int)$ban_id) or error(db_error());
if (!$dont_rebuild) Vichan\Functions\Theme\rebuild_themes('bans');
return true;
}
static public function new_ban($mask, $reason, $length = false, $ban_board = false, $mod_id = false, $post = false) {
static public function new_ban($cloaked_mask, $reason, $length = false, $ban_board = false, $mod_id = false, $post = false) {
$mask = uncloak_mask($cloaked_mask);
global $mod, $pdo, $board;
if ($mod_id === false) {
@ -206,6 +402,7 @@ class Bans {
$range = self::parse_range($mask);
$mask = self::range_to_string($range);
$cloaked_mask = cloak_mask($mask);
$query = prepare("INSERT INTO ``bans`` VALUES (NULL, :ipstart, :ipend, :time, :expires, :board, :mod, :reason, 0, :post)");
@ -242,23 +439,34 @@ class Bans {
$query->bindValue(':board', null, PDO::PARAM_NULL);
if ($post) {
if (!isset($board['uri']))
openBoard($post['board']);
$post['board'] = $board['uri'];
/*
* The body can be so long to make the json longer than 64KBs, causing the query to fail.
* Truncate it to a safe length (32KBs). It could probably be longer, but if the deleted body is THAT big
* already, the likelihood of it being just assorted spam/garbage is about 101%.
*/
// We're on UTF-8 only, right...?
$post['body'] = mb_strcut($post['body'], 0, 32768);
$query->bindValue(':post', json_encode($post));
} else
$query->bindValue(':post', null, PDO::PARAM_NULL);
$query->execute() or error(db_error($query));
if (isset($mod['id']) && $mod['id'] == $mod_id) {
modLog('Created a new ' .
($length > 0 ? preg_replace('/^(\d+) (\w+?)s?$/', '$1-$2', until($length)) : 'permanent') .
' ban on ' .
($ban_board ? '/' . $ban_board . '/' : 'all boards') .
' for ' .
(filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/$mask\">$mask</a>" : $mask) .
' (<small>#' . $pdo->lastInsertId() . '</small>)' .
' with ' . ($reason ? 'reason: ' . utf8tohtml($reason) . '' : 'no reason'));
}
$ban_len = $length > 0 ? preg_replace('/^(\d+) (\w+?)s?$/', '$1-$2', Format\until($length)) : 'permanent';
$ban_board = $ban_board ? "/$ban_board/" : 'all boards';
$ban_ip = filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/$cloaked_mask\">$cloaked_mask</a>" : $cloaked_mask;
$ban_id = $pdo->lastInsertId();
$ban_reason = $reason ? 'reason: ' . utf8tohtml($reason) : 'no reason';
modLog("Created a new $ban_len ban on $ban_board for $ban_ip (<small># $ban_id </small>) with $ban_reason");
Vichan\Functions\Theme\rebuild_themes('bans');
return $pdo->lastInsertId();
}
}

3
inc/bootstrap.php Normal file
View File

@ -0,0 +1,3 @@
<?php
@define('TINYBOARD', 'xD');
require_once('vendor/autoload.php');

View File

@ -4,143 +4,89 @@
* Copyright (c) 2010-2013 Tinyboard Development Group
*/
use Vichan\Data\Driver\{CacheDriver, ApcuCacheDriver, ArrayCacheDriver, FsCacheDriver, MemcachedCacheDriver, NoneCacheDriver, RedisCacheDriver};
defined('TINYBOARD') or exit;
class Cache {
private static $cache;
public static function init() {
private static function buildCache(): CacheDriver {
global $config;
switch ($config['cache']['enabled']) {
case 'memcached':
self::$cache = new Memcached();
self::$cache->addServers($config['cache']['memcached']);
break;
return new MemcachedCacheDriver(
$config['cache']['prefix'],
$config['cache']['memcached']
);
case 'redis':
self::$cache = new Redis();
self::$cache->connect($config['cache']['redis'][0], $config['cache']['redis'][1]);
if ($config['cache']['redis'][2]) {
self::$cache->auth($config['cache']['redis'][2]);
}
self::$cache->select($config['cache']['redis'][3]) or die('cache select failure');
break;
return new RedisCacheDriver(
$config['cache']['prefix'],
$config['cache']['redis'][0],
$config['cache']['redis'][1],
$config['cache']['redis'][2],
$config['cache']['redis'][3]
);
case 'apcu':
return new ApcuCacheDriver;
case 'fs':
return new FsCacheDriver(
$config['cache']['prefix'],
"tmp/cache/{$config['cache']['prefix']}",
'.lock',
$config['auto_maintenance'] ? 1000 : false
);
case 'none':
return new NoneCacheDriver();
case 'php':
self::$cache = array();
break;
default:
return new ArrayCacheDriver();
}
}
public static function getCache(): CacheDriver {
static $cache;
return $cache ??= self::buildCache();
}
public static function get($key) {
global $config, $debug;
$key = $config['cache']['prefix'] . $key;
$data = false;
switch ($config['cache']['enabled']) {
case 'memcached':
if (!self::$cache)
self::init();
$data = self::$cache->get($key);
break;
case 'apc':
$data = apc_fetch($key);
break;
case 'xcache':
$data = xcache_get($key);
break;
case 'php':
$data = isset(self::$cache[$key]) ? self::$cache[$key] : false;
break;
case 'redis':
if (!self::$cache)
self::init();
$data = json_decode(self::$cache->get($key), true);
break;
$ret = self::getCache()->get($key);
if ($ret === null) {
$ret = false;
}
if ($config['debug'])
$debug['cached'][] = $key . ($data === false ? ' (miss)' : ' (hit)');
if ($config['debug']) {
$debug['cached'][] = $config['cache']['prefix'] . $key . ($ret === false ? ' (miss)' : ' (hit)');
}
return $data;
return $ret;
}
public static function set($key, $value, $expires = false) {
global $config, $debug;
$key = $config['cache']['prefix'] . $key;
if (!$expires)
if (!$expires) {
$expires = $config['cache']['timeout'];
switch ($config['cache']['enabled']) {
case 'memcached':
if (!self::$cache)
self::init();
self::$cache->set($key, $value, $expires);
break;
case 'redis':
if (!self::$cache)
self::init();
self::$cache->setex($key, $expires, json_encode($value));
break;
case 'apc':
apc_store($key, $value, $expires);
break;
case 'xcache':
xcache_set($key, $value, $expires);
break;
case 'php':
self::$cache[$key] = $value;
break;
}
if ($config['debug'])
$debug['cached'][] = $key . ' (set)';
self::getCache()->set($key, $value, $expires);
if ($config['debug']) {
$debug['cached'][] = $config['cache']['prefix'] . $key . ' (set)';
}
}
public static function delete($key) {
global $config, $debug;
$key = $config['cache']['prefix'] . $key;
self::getCache()->delete($key);
switch ($config['cache']['enabled']) {
case 'memcached':
case 'redis':
if (!self::$cache)
self::init();
self::$cache->delete($key);
break;
case 'apc':
apc_delete($key);
break;
case 'xcache':
xcache_unset($key);
break;
case 'php':
unset(self::$cache[$key]);
break;
if ($config['debug']) {
$debug['cached'][] = $config['cache']['prefix'] . $key . ' (deleted)';
}
if ($config['debug'])
$debug['cached'][] = $key . ' (deleted)';
}
public static function flush() {
global $config;
switch ($config['cache']['enabled']) {
case 'memcached':
if (!self::$cache)
self::init();
return self::$cache->flush();
case 'apc':
return apc_clear_cache('user');
case 'php':
self::$cache = array();
break;
case 'redis':
if (!self::$cache)
self::init();
return self::$cache->flushDB();
}
self::getCache()->flush();
return false;
}
}

357
inc/captcha/captcha.php Normal file
View File

@ -0,0 +1,357 @@
<?php
class CzaksCaptcha {
var $content = array();
var $width, $height, $color, $charset, $style;
function __construct($text, $left, $top, $charset=false) {
if (!$charset) {
$charset = 'abcdefghijklmnopqrstuvwxyz';
}
$len = mb_strlen($text, 'utf-8');
$this->width = $left;
$this->height = $top;
$this->charset = preg_split('//u', $charset);
$this->style = "";
for ($i = 0; $i < $len; $i++) {
$this->content[] = array(mb_substr($text, $i, 1, 'utf-8'), "top" => $top / 2 - $top / 4,
"left" => $left/10 + 9*$left*$i/10/$len,
"position" => "absolute");
}
$this->color = "hsla(".rand(1,360).", 76%, 78%, 1)";
$this->add_junk();
$this->mutate_sizes();
$this->mutate_positions();
$this->mutate_transform();
$this->mutate_anchors();
$this->randomize();
$this->mutate_containers();
$this->mutate_margins();
$this->mutate_styles();
$this->randomize();
}
function mutate_sizes() {
foreach ($this->content as &$v) {
if (!isset ($v['font-size']))
$v['font-size'] = rand(intval($this->height/3) - 4, intval($this->height/3) + 8);
}
}
function mutate_positions() {
foreach ($this->content as &$v) {
$v['top'] += rand(-10,10);
$v['left'] += rand(-10,10);
}
}
function mutate_transform() {
$fromto = array('6'=>'9', '9'=>'6', '8'=>'8', '0'=>'0',
'z'=>'z', 's'=>'s', 'n'=>'u', 'u'=>'n',
'a'=>'ɐ', 'e'=>'ə', 'p'=>'d', 'd'=>'p',
'A'=>'∀', 'E'=>'∃', 'H'=>'H', 'o'=>'o',
'O'=>'O');
foreach ($this->content as &$v) {
$basefrom = -20;
$baseto = 20;
if (isset($fromto[$v[0]]) && rand(0,1)) {
$v[0] = $fromto[$v[0]];
$basefrom = 160;
$baseto = 200;
}
$v['transform'] = 'rotate('.rand($basefrom,$baseto).'deg)';
$v['-ms-transform'] = 'rotate('.rand($basefrom,$baseto).'deg)';
$v['-webkit-transform'] = 'rotate('.rand($basefrom,$baseto).'deg)';
}
}
function randomize(&$a = false) {
if ($a === false) {
$a = &$this->content;
}
shuffle($a);
foreach ($a as &$v) {
$this->shuffle_assoc($v);
if (is_array ($v[0])) {
$this->randomize($v[0]);
}
}
}
function add_junk() {
$count = rand(200, 300);
while ($count--) {
$elem = array();
$elem['top'] = rand(0, $this->height);
$elem['left'] = rand(0, $this->width);
$elem['position'] = 'absolute';
$elem[0] = $this->charset[rand(0, count($this->charset)-1)];
switch($t = rand (0,9)) {
case 0:
$elem['display'] = 'none'; break;
case 1:
$elem['top'] = rand(-60, -90); break;
case 2:
$elem['left'] = rand(-40, -70); break;
case 3:
$elem['top'] = $this->height + rand(10, 60); break;
case 4:
$elem['left'] = $this->width + rand(10, 60); break;
case 5:
$elem['color'] = $this->color; break;
case 6:
$elem['visibility'] = 'hidden'; break;
case 7:
$elem['height'] = rand(0,2);
$elem['overflow'] = 'hidden'; break;
case 8:
$elem['width'] = rand(0,1);
$elem['overflow'] = 'hidden'; break;
case 9:
$elem['font-size'] = rand(2, 6); break;
}
$this->content[] = $elem;
}
}
function mutate_anchors() {
foreach ($this->content as &$elem) {
if (rand(0,1)) {
$elem['right'] = $this->width - $elem['left'] - (int)(0.5*$elem['font-size']);
unset($elem['left']);
}
if (rand(0,1)) {
$elem['bottom'] = $this->height - $elem['top'] - (int)(1.5*$elem['font-size']);
unset($elem['top']);
}
}
}
function mutate_containers() {
for ($i = 0; $i <= 80; $i++) {
$new = [];
$new['width'] = rand(0, $this->width*2);
$new['height'] = rand(0, $this->height*2);
$new['top'] = rand(-$this->height * 2, $this->height * 2);
$new['bottom'] = $this->height - ($new['top'] + $new['height']);
$new['left'] = rand(-$this->width * 2, $this->width * 2);
$new['right'] = $this->width - ($new['left'] + $new['width']);
$new['position'] = 'absolute';
$new[0] = [];
$cnt = rand(0,10);
for ($j = 0; $j < $cnt; $j++) {
$elem = array_pop($this->content);
if (!$elem) break;
if (isset($elem['top'])) $elem['top'] -= $new['top'];
if (isset($elem['bottom'])) $elem['bottom'] -= $new['bottom'];
if (isset($elem['left'])) $elem['left'] -= $new['left'];
if (isset($elem['right'])) $elem['right'] -= $new['right'];
$new[0][] = $elem;
}
if (rand (0,1)) unset($new['top']);
else unset($new['bottom']);
if (rand (0,1)) unset($new['left']);
else unset($new['right']);
$this->content[] = $new;
shuffle($this->content);
}
}
function mutate_margins(&$a = false) {
if ($a === false) {
$a = &$this->content;
}
foreach ($a as &$v) {
$ary = ['top', 'left', 'bottom', 'right'];
shuffle($ary);
$cnt = rand(0,4);
$ary = array_slice($ary, 0, $cnt);
foreach ($ary as $prop) {
$margin = rand(-1000, 1000);
$v['margin-'.$prop] = $margin;
if (isset($v[$prop])) {
$v[$prop] -= $margin;
}
}
if (is_array($v[0])) {
$this->mutate_margins($v[0]);
}
}
}
function mutate_styles(&$a = false) {
if ($a === false) {
$a = &$this->content;
}
foreach ($a as &$v) {
$content = $v[0];
unset($v[0]);
$styles = array_splice($v, 0, rand(0, 6));
$v[0] = $content;
$id_or_class = rand(0,1);
$param = $id_or_class ? "id" : "class";
$prefix = $id_or_class ? "#" : ".";
$genname = "zz-".base_convert(rand(1,999999999), 10, 36);
if ($styles || rand(0,1)) {
$this->style .= $prefix.$genname."{";
$this->style .= $this->rand_whitespace();
foreach ($styles as $k => $val) {
if (is_int($val)) {
$val = "".$val."px";
}
$this->style .= "$k:";
$this->style .= $this->rand_whitespace();
$this->style .= "$val;";
$this->style .= $this->rand_whitespace();
}
$this->style .= "}";
$this->style .= $this->rand_whitespace();
}
$v[$param] = $genname;
if (is_array($v[0])) {
$this->mutate_styles($v[0]);
}
}
}
function to_html(&$a = false) {
$inside = true;
if ($a === false) {
if ($this->style) {
echo "<style type='text/css'>";
echo $this->style;
echo "</style>";
}
echo "<div style='position: relative; width: ".$this->width."px; height: ".$this->height."px; overflow: hidden; background-color: ".$this->color."'>";
$a = &$this->content;
$inside = false;
}
foreach ($a as &$v) {
$letter = $v[0];
unset ($v[0]);
echo "<div";
echo $this->rand_whitespace(1);
if (isset ($v['id'])) {
echo "id='$v[id]'";
echo $this->rand_whitespace(1);
unset ($v['id']);
}
if (isset ($v['class'])) {
echo "class='$v[class]'";
echo $this->rand_whitespace(1);
unset ($v['class']);
}
echo "style='";
foreach ($v as $k => $val) {
if (is_int($val)) {
$val = "".$val."px";
}
echo "$k:";
echo $this->rand_whitespace();
echo "$val;";
echo $this->rand_whitespace();
}
echo "'>";
echo $this->rand_whitespace();
if (is_array ($letter)) {
$this->to_html($letter);
}
else {
echo $letter;
}
echo "</div>";
}
if (!$inside) {
echo "</div>";
}
}
function rand_whitespace($r = 0) {
switch (rand($r,4)) {
case 0:
return "";
case 1:
return "\n";
case 2:
return "\t";
case 3:
return " ";
case 4:
return " ";
}
}
function shuffle_assoc(&$array) {
$keys = array_keys($array);
shuffle($keys);
foreach($keys as $key) {
$new[$key] = $array[$key];
}
$array = $new;
return true;
}
}
//$charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789卐";
//(new CzaksCaptcha("hotwheels", 300, 80, $charset))->to_html();
?>

16
inc/captcha/config.php Normal file
View File

@ -0,0 +1,16 @@
<?php
// We are using a custom path here to connect to the database.
// Why? Performance reasons.
$pdo = new PDO("mysql:dbname=database_name;host=localhost", "database_user", "database_password", array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
// Captcha expiration:
$expires_in = 120; // 120 seconds
// Captcha dimensions:
$width = 250;
$height = 80;
// Captcha length:
$length = 6;

View File

@ -0,0 +1,85 @@
<?php
$mode = @$_GET['mode'];
require_once("captcha.php");
function rand_string($length, $charset) {
$ret = "";
while ($length--) {
$ret .= mb_substr($charset, rand(0, mb_strlen($charset, 'utf-8')-1), 1, 'utf-8');
}
return $ret;
}
function cleanup ($pdo, $expires_in) {
$pdo->prepare("DELETE FROM `captchas` WHERE `created_at` < ?")->execute([time() - $expires_in]);
}
switch ($mode) {
// Request: GET entrypoint.php?mode=get&extra=1234567890
// Response: JSON: cookie => "generatedcookie", captchahtml => "captchahtml", expires_in => 120
case "get":
if (!isset ($_GET['extra'])) {
die();
}
header("Content-type: application/json");
$extra = $_GET['extra'];
require_once("config.php");
$text = rand_string($length, $extra);
$captcha = new CzaksCaptcha($text, $width, $height, $extra);
$cookie = rand_string(20, "abcdefghijklmnopqrstuvwxyz");
ob_start();
$captcha->to_html();
$html = ob_get_contents();
ob_end_clean();
$query = $pdo->prepare("INSERT INTO `captchas` (`cookie`, `extra`, `text`, `created_at`) VALUES (?, ?, ?, ?)");
$query->execute( [$cookie, $extra, $text, time()]);
echo json_encode(["cookie" => $cookie, "captchahtml" => $html, "expires_in" => $expires_in]);
break;
// Request: GET entrypoint.php?mode=check&cookie=generatedcookie&extra=1234567890&text=captcha
// Response: 0 OR 1
case "check":
if (!isset ($_GET['mode'])
|| !isset ($_GET['cookie'])
|| !isset ($_GET['extra'])
|| !isset ($_GET['text'])) {
die();
}
require_once("config.php");
cleanup($pdo, $expires_in);
$query = $pdo->prepare("SELECT * FROM `captchas` WHERE `cookie` = ? AND `extra` = ?");
$query->execute([$_GET['cookie'], $_GET['extra']]);
$ary = $query->fetchAll();
if (!$ary) {
echo "0";
}
else {
$query = $pdo->prepare("DELETE FROM `captchas` WHERE `cookie` = ? AND `extra` = ?");
$query->execute([$_GET['cookie'], $_GET['extra']]);
if ($ary[0]['text'] !== $_GET['text']) {
echo "0";
}
else {
echo "1";
}
}
break;
}

8
inc/captcha/readme.md Normal file
View File

@ -0,0 +1,8 @@
I integrated this from: https://github.com/ctrlcctrlv/infinity/commit/62a6dac022cb338f7b719d0c35a64ab3efc64658
In inc/captcha/config.php change the database_name database_user database_password to your own settings.
Add js/captcha.js in your secrets.php or config.php
Go to Line 305 in the /inc/config file and copy the settings in instance config, while changing the url to your website.
Go to the line beneath it if you only want to enable it when posting a new thread.

File diff suppressed because it is too large Load Diff

91
inc/context.php Normal file
View File

@ -0,0 +1,91 @@
<?php
namespace Vichan;
use Vichan\Data\Driver\{CacheDriver, HttpDriver, ErrorLogLogDriver, FileLogDriver, LogDriver, StderrLogDriver, SyslogLogDriver};
use Vichan\Service\HCaptchaQuery;
use Vichan\Service\NativeCaptchaQuery;
use Vichan\Service\ReCaptchaQuery;
use Vichan\Service\RemoteCaptchaQuery;
defined('TINYBOARD') or exit;
class Context {
private array $definitions;
public function __construct(array $definitions) {
$this->definitions = $definitions;
}
public function get(string $name){
if (!isset($this->definitions[$name])) {
throw new \RuntimeException("Could not find a dependency named $name");
}
$ret = $this->definitions[$name];
if (is_callable($ret) && !is_string($ret) && !is_array($ret)) {
$ret = $ret($this);
$this->definitions[$name] = $ret;
}
return $ret;
}
}
function build_context(array $config): Context {
return new Context([
'config' => $config,
LogDriver::class => function($c) {
$config = $c->get('config');
$name = $config['log_system']['name'];
$level = $config['debug'] ? LogDriver::DEBUG : LogDriver::NOTICE;
$backend = $config['log_system']['type'];
// Check 'syslog' for backwards compatibility.
if ((isset($config['syslog']) && $config['syslog']) || $backend === 'syslog') {
return new SyslogLogDriver($name, $level, $this->config['log_system']['syslog_stderr']);
} elseif ($backend === 'file') {
return new FileLogDriver($name, $level, $this->config['log_system']['file_path']);
} elseif ($backend === 'stderr') {
return new StderrLogDriver($name, $level);
} else {
return new ErrorLogLogDriver($name, $level);
}
},
HttpDriver::class => function($c) {
$config = $c->get('config');
return new HttpDriver($config['upload_by_url_timeout'], $config['max_filesize']);
},
RemoteCaptchaQuery::class => function($c) {
$config = $c->get('config');
$http = $c->get(HttpDriver::class);
switch ($config['captcha']['provider']) {
case 'recaptcha':
return new ReCaptchaQuery($http, $config['captcha']['recaptcha']['secret']);
case 'hcaptcha':
return new HCaptchaQuery(
$http,
$config['captcha']['hcaptcha']['secret'],
$config['captcha']['hcaptcha']['sitekey']
);
default:
throw new \RuntimeException('No remote captcha service available');
}
},
NativeCaptchaQuery::class => function($c) {
$config = $c->get('config');
if ($config['captcha']['provider'] !== 'native') {
throw new \RuntimeException('No native captcha service available');
}
return new NativeCaptchaQuery(
$c->get(HttpDriver::class),
$config['domain'],
$config['captcha']['native']['provider_check'],
$config['captcha']['native']['extra']
);
},
CacheDriver::class => function($c) {
// Use the global for backwards compatibility.
return \cache::getCache();
}
]);
}

108
inc/controller.php Normal file
View File

@ -0,0 +1,108 @@
<?php
// This file contains the controller part of vichan
// don't bother with that unless you use smart build or advanced build
// you can use those parts for your own implementations though :^)
defined('TINYBOARD') or exit;
function sb_board($b, $page = 1) { global $config, $build_pages; $page = (int)$page;
if ($page < 1) return false;
if (!openBoard($b)) return false;
if ($page > $config['max_pages']) return false;
$config['try_smarter'] = true;
$build_pages = array($page);
buildIndex("skip");
return true;
}
function sb_api_board($b, $page = 0) { $page = (int)$page;
return sb_board($b, $page + 1);
}
function sb_thread($b, $thread, $slugcheck = false) { global $config; $thread = (int)$thread;
if ($thread < 1) return false;
if (!preg_match('/^'.$config['board_regex'].'$/u', $b)) return false;
if (Cache::get("thread_exists_".$b."_".$thread) == "no") return false;
$query = prepare(sprintf("SELECT MAX(`id`) AS `max` FROM ``posts_%s``", $b));
if (!$query->execute()) return false;
$s = $query->fetch(PDO::FETCH_ASSOC);
$max = $s['max'];
if ($thread > $max) return false;
$query = prepare(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL", $b));
$query->bindValue(':id', $thread);
if (!$query->execute() || !$query->fetch(PDO::FETCH_ASSOC) ) {
Cache::set("thread_exists_".$b."_".$thread, "no", 3600);
return false;
}
if ($slugcheck && $config['slugify']) {
global $request;
$link = link_for(array("id" => $thread), $slugcheck === 50, array("uri" => $b));
$link = "/".$b."/".$config['dir']['res'].$link;
if ($link != $request) {
header("Location: $link", true, 301);
die();
}
}
if ($slugcheck == 50) { // Should we really generate +50 page? Maybe there are not enough posts anyway
global $request;
$r = str_replace("+50", "", $request);
$r = substr($r, 1); // Cut the slash
if (file_exists($r)) return false;
}
if (!openBoard($b)) return false;
buildThread($thread);
return true;
}
function sb_thread_slugcheck($b, $thread) {
return sb_thread($b, $thread, true);
}
function sb_thread_slugcheck50($b, $thread) {
return sb_thread($b, $thread, 50);
}
function sb_api($b) { global $config, $build_pages;
if (!openBoard($b)) return false;
$config['try_smarter'] = true;
$build_pages = array(-1);
buildIndex();
return true;
}
function sb_ukko() {
Vichan\Functions\Theme\rebuild_theme("ukko", "post-thread");
return true;
}
function sb_catalog($b) {
if (!openBoard($b)) return false;
Vichan\Functions\Theme\rebuild_theme("catalog", "post-thread", $b);
return true;
}
function sb_recent() {
Vichan\Functions\Theme\rebuild_theme("recent", "post-thread");
return true;
}
function sb_sitemap() {
Vichan\Functions\Theme\rebuild_theme("sitemap", "all");
return true;
}

View File

@ -103,7 +103,7 @@ function mysql_version() {
$v = explode('.', $version);
if (count($v) != 3)
return false;
return (int) sprintf("%02d%02d%02d", $v[0], $v[1], $v[2]);
return (int) sprintf("%02d%02d%02d", $v[0], $v[1], is_int($v[2]) ? (int)$v[2] : 0);
}
function prepare($query) {

View File

@ -71,7 +71,7 @@ function createBoardlist($mod=false) {
);
}
function error($message, $priority = true, $debug_stuff = false) {
function error($message, $priority = true, $debug_stuff = []) {
global $board, $mod, $config, $db_error;
if ($config['syslog'] && $priority !== false) {
@ -81,38 +81,51 @@ function error($message, $priority = true, $debug_stuff = false) {
if (defined('STDIN')) {
// Running from CLI
die('Error: ' . $message . "\n");
echo('Error: ' . $message . "\n");
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
die();
}
if ($config['debug'] && isset($db_error)) {
$debug_stuff = array_combine(array('SQLSTATE', 'Error code', 'Error message'), $db_error);
}
// Return the bad request header, necessary for AJAX posts
// czaks: is it really so? the ajax errors only work when this is commented out
// better yet use it when ajax is disabled
if (!isset ($_POST['json_response'])) {
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
if ($config['debug']) {
$debug_stuff['backtrace'] = debug_backtrace();
}
// Is there a reason to disable this?
if (isset($_POST['json_response'])) {
header('Content-Type: text/json; charset=utf-8');
die(json_encode(array(
'error' => $message
)));
}
else {
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
}
die(Element('page.html', array(
$pw = $config['db']['password'];
$debug_callback = function($item) use (&$debug_callback, $pw) {
if (is_array($item)) {
$item = array_filter($item, $debug_callback);
}
return ($item !== $pw || !$pw);
};
if ($debug_stuff)
$debug_stuff = array_filter($debug_stuff, $debug_callback);
die(Element($config['file_page_template'], array(
'config' => $config,
'title' => _('Error'),
'subtitle' => _('An error has occured.'),
'body' => Element('error.html', array(
'body' => Element($config['file_error'], array(
'config' => $config,
'message' => $message,
'mod' => $mod,
'board' => isset($board) ? $board : false,
'debug' => is_array($debug_stuff) ? str_replace("\n", '&#10;', utf8tohtml(print_r($debug_stuff, true))) : utf8tohtml($debug_stuff)
'debug' => $config['debug'] ? (is_array($debug_stuff) ? str_replace("\n", '&#10;', utf8tohtml(print_r($debug_stuff, true))) : utf8tohtml($debug_stuff)) : null
))
)));
}
@ -120,11 +133,11 @@ function error($message, $priority = true, $debug_stuff = false) {
function loginForm($error=false, $username=false, $redirect=false) {
global $config;
die(Element('page.html', array(
die(Element($config['file_page_template'], array(
'index' => $config['root'],
'title' => _('Login'),
'config' => $config,
'body' => Element('login.html', array(
'body' => Element($config['file_login'], array(
'config'=>$config,
'error'=>$error,
'username'=>utf8tohtml($username),
@ -335,6 +348,26 @@ class Post {
$this->{$key} = $value;
}
if (isset($this->files) && $this->files) {
$this->files = is_string($this->files) ? json_decode($this->files) : $this->files;
// Compatibility for posts before individual file hashing
foreach ($this->files as $i => &$file) {
if (empty($file)) {
unset($this->files[$i]);
continue;
}
if (is_array($file)) {
if (!isset($file['hash'])) {
$file['hash'] = $this->filehash;
}
} else if (is_object($file)) {
if (!isset($file->hash)) {
$file->hash = $this->filehash;
}
}
}
}
$this->subject = utf8tohtml($this->subject);
$this->name = utf8tohtml($this->name);
$this->mod = $mod;
@ -359,69 +392,27 @@ class Post {
$this->body
);
}
public function link($pre = '') {
public function link($pre = '', $page = false) {
global $config, $board;
return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->thread) . '#' . $pre . $this->id;
}
public function postControls() {
global $board, $config;
$built = '';
if ($this->mod) {
// Mod controls (on posts)
// Delete
if (hasPermission($config['mod']['delete'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['dir'] . 'delete/' . $this->id);
// Delete all posts by IP
if (hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by this IP address?', $board['dir'] . 'deletebyip/' . $this->id);
// Delete all posts by IP (global)
if (hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_deletebyip_global'], 'Delete all posts by IP across all boards', 'Are you sure you want to delete all posts by this IP address, across all boards?', $board['dir'] . 'deletebyip/' . $this->id . '/global');
// Ban
if (hasPermission($config['mod']['ban'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Ban').'" href="?/' . $board['dir'] . 'ban/' . $this->id . '">' . $config['mod']['link_ban'] . '</a>';
// Ban & Delete
if (hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Ban & Delete').'" href="?/' . $board['dir'] . 'ban&amp;delete/' . $this->id . '">' . $config['mod']['link_bandelete'] . '</a>';
// Delete file (keep post)
if (!empty($this->file) && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id);
// Spoiler file (keep post)
if (!empty($this->file) && $this->file != "deleted" && $this->file != null && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images'])
$built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], _('Spoiler File'), _('Are you sure you want to spoiler this file?'), $board['uri'] . '/spoiler/' . $this->id);
// Move post
if (hasPermission($config['mod']['move'], $board['uri'], $this->mod) && $config['move_replies'])
$built .= ' <a title="'._('Move reply to another board').'" href="?/' . $board['uri'] . '/move_reply/' . $this->id . '">' . $config['mod']['link_move'] . '</a>';
// Edit post
if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Edit post').'" href="?/' . $board['dir'] . 'edit' . ($config['mod']['raw_html_default'] ? '_raw' : '') . '/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>';
if (!empty($built))
$built = '<span class="controls">' . $built . '</span>';
}
return $built;
}
public function ratio() {
return fraction($this->filewidth, $this->fileheight, ':');
return $this->root . $board['dir'] . $config['dir']['res'] . link_for((array)$this, $page == '50') . '#' . $pre . $this->id;
}
public function build($index=false) {
global $board, $config;
return Element('post_reply.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index));
$options = [
'config' => $config,
'board' => $board,
'post' => &$this,
'index' => $index,
'mod' => $this->mod
];
if ($this->mod) {
$options['pm'] = create_pm_header();
}
return Element($config['file_post_reply'], $options);
}
};
@ -435,6 +426,9 @@ class Thread {
$this->{$key} = $value;
}
if (isset($this->files))
$this->files = is_string($this->files) ? json_decode($this->files) : $this->files;
$this->subject = utf8tohtml($this->subject);
$this->name = utf8tohtml($this->name);
$this->mod = $mod;
@ -464,88 +458,17 @@ class Thread {
$this->body
);
}
public function link($pre = '') {
public function link($pre = '', $page = false) {
global $config, $board;
return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->id) . '#' . $pre . $this->id;
return $this->root . $board['dir'] . $config['dir']['res'] . link_for((array)$this, $page == '50') . '#' . $pre . $this->id;
}
public function add(Post $post) {
$this->posts[] = $post;
}
public function postCount() {
return count($this->posts) + $this->omitted;
return count($this->posts) + $this->omitted;
}
public function postControls() {
global $board, $config;
$built = '';
if ($this->mod) {
// Mod controls (on posts)
// Delete
if (hasPermission($config['mod']['delete'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_delete'], _('Delete'), _('Are you sure you want to delete this?'), $board['dir'] . 'delete/' . $this->id);
// Delete all posts by IP
if (hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_deletebyip'], _('Delete all posts by IP'), _('Are you sure you want to delete all posts by this IP address?'), $board['dir'] . 'deletebyip/' . $this->id);
// Delete all posts by IP (global)
if (hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_deletebyip_global'], _('Delete all posts by IP across all boards'), _('Are you sure you want to delete all posts by this IP address, across all boards?'), $board['dir'] . 'deletebyip/' . $this->id . '/global');
// Ban
if (hasPermission($config['mod']['ban'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Ban').'" href="?/' . $board['dir'] . 'ban/' . $this->id . '">' . $config['mod']['link_ban'] . '</a>';
// Ban & Delete
if (hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Ban & Delete').'" href="?/' . $board['dir'] . 'ban&amp;delete/' . $this->id . '">' . $config['mod']['link_bandelete'] . '</a>';
// Delete file (keep post)
if (!empty($this->file) && $this->file != 'deleted' && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod))
$built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id);
// Spoiler file (keep post)
if (!empty($this->file) && $this->file != "deleted" && $this->file != null && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images'])
$built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], _('Spoiler File'), _('Are you sure you want to spoiler this file?'), $board['uri'] . '/spoiler/' . $this->id);
// Sticky
if (hasPermission($config['mod']['sticky'], $board['uri'], $this->mod))
if ($this->sticky)
$built .= ' <a title="'._('Make thread not sticky').'" href="?/' . secure_link($board['dir'] . 'unsticky/' . $this->id) . '">' . $config['mod']['link_desticky'] . '</a>';
else
$built .= ' <a title="'._('Make thread sticky').'" href="?/' . secure_link($board['dir'] . 'sticky/' . $this->id) . '">' . $config['mod']['link_sticky'] . '</a>';
if (hasPermission($config['mod']['bumplock'], $board['uri'], $this->mod))
if ($this->sage)
$built .= ' <a title="'._('Allow thread to be bumped').'" href="?/' . secure_link($board['dir'] . 'bumpunlock/' . $this->id) . '">' . $config['mod']['link_bumpunlock'] . '</a>';
else
$built .= ' <a title="'._('Prevent thread from being bumped').'" href="?/' . secure_link($board['dir'] . 'bumplock/' . $this->id) . '">' . $config['mod']['link_bumplock'] . '</a>';
// Lock
if (hasPermission($config['mod']['lock'], $board['uri'], $this->mod))
if ($this->locked)
$built .= ' <a title="'._('Unlock thread').'" href="?/' . secure_link($board['dir'] . 'unlock/' . $this->id) . '">' . $config['mod']['link_unlock'] . '</a>';
else
$built .= ' <a title="'._('Lock thread').'" href="?/' . secure_link($board['dir'] . 'lock/' . $this->id) . '">' . $config['mod']['link_lock'] . '</a>';
if (hasPermission($config['mod']['move'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Move thread to another board').'" href="?/' . $board['dir'] . 'move/' . $this->id . '">' . $config['mod']['link_move'] . '</a>';
// Edit post
if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Edit post').'" href="?/' . $board['dir'] . 'edit' . ($config['mod']['raw_html_default'] ? '_raw' : '') . '/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>';
if (!empty($built))
$built = '<span class="controls op">' . $built . '</span>';
}
return $built;
}
public function ratio() {
return fraction($this->filewidth, $this->fileheight, ':');
}
public function build($index=false, $isnoko50=false) {
global $board, $config, $debug;
@ -553,9 +476,22 @@ class Thread {
event('show-thread', $this);
$built = Element('post_thread.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'hasnoko50' => $hasnoko50, 'isnoko50' => $isnoko50));
$options = [
'config' => $config,
'board' => $board,
'post' => &$this,
'index' => $index,
'hasnoko50' => $hasnoko50,
'isnoko50' => $isnoko50,
'mod' => $this->mod
];
if ($this->mod) {
$options['pm'] = create_pm_header();
}
$file = ($index && $config['file_board']) ? $config['file_post_thread_fileboard'] : $config['file_post_thread'];
$built = Element($file, $options);
return $built;
}
};

View File

@ -9,23 +9,29 @@ defined('TINYBOARD') or exit;
class Filter {
public $flood_check;
private $condition;
private $post;
public function __construct(array $arr) {
foreach ($arr as $key => $value)
foreach ($arr as $key => $value) {
$this->$key = $value;
}
}
public function match(array $post, $condition, $match) {
public function match($condition, $match) {
$condition = strtolower($condition);
$post = &$this->post;
switch($condition) {
case 'custom':
if (!is_callable($match))
if (!is_callable($match)) {
error('Custom condition for filter is not callable!');
}
return $match($post);
case 'flood-match':
if (!is_array($match))
if (!is_array($match)) {
error('Filter condition "flood-match" must be an array.');
}
// Filter out "flood" table entries which do not match this filter.
@ -35,26 +41,32 @@ class Filter {
foreach ($match as $flood_match_arg) {
switch ($flood_match_arg) {
case 'ip':
if ($flood_post['ip'] != $_SERVER['REMOTE_ADDR'])
if ($flood_post['ip'] != $_SERVER['REMOTE_ADDR']) {
continue 3;
}
break;
case 'body':
if ($flood_post['posthash'] != make_comment_hex($post['body_nomarkup']))
if ($flood_post['posthash'] != make_comment_hex($post['body_nomarkup'])) {
continue 3;
}
break;
case 'file':
if (!isset($post['filehash']))
if (!isset($post['filehash'])) {
return false;
if ($flood_post['filehash'] != $post['filehash'])
}
if ($flood_post['filehash'] != $post['filehash']) {
continue 3;
}
break;
case 'board':
if ($flood_post['board'] != $post['board'])
if ($flood_post['board'] != $post['board']) {
continue 3;
}
break;
case 'isreply':
if ($flood_post['isreply'] == $post['op'])
if ($flood_post['isreply'] == $post['op']) {
continue 3;
}
break;
default:
error('Invalid filter flood condition: ' . $flood_match_arg);
@ -64,7 +76,6 @@ class Filter {
}
$this->flood_check = $flood_check_matched;
return !empty($this->flood_check);
case 'flood-time':
foreach ($this->flood_check as $flood_post) {
@ -94,19 +105,45 @@ class Filter {
case 'filehash':
return $match === $post['filehash'];
case 'filename':
if (!$post['has_file'])
if (!$post['files']) {
return false;
return preg_match($match, $post['filename']);
}
foreach ($post['files'] as $file) {
if (preg_match($match, $file['filename'])) {
return true;
}
}
return false;
case 'extension':
if (!$post['has_file'])
if (!$post['files']) {
return false;
return preg_match($match, $post['body']);
}
foreach ($post['files'] as $file) {
if (preg_match($match, $file['extension'])) {
return true;
}
}
return false;
case 'ip':
return preg_match($match, $_SERVER['REMOTE_ADDR']);
case 'op':
return $post['op'] == $match;
case 'has_file':
return $post['has_file'] == $match;
case 'board':
return $post['board'] == $match;
case 'password':
return $post['password'] == $match;
case 'unshorten':
$extracted_urls = get_urls($post['body_nomarkup']);
foreach ($extracted_urls as $url) {
if (preg_match($match, trace_url($url))) {
return true;
}
}
return false;
default:
error('Unknown filter condition: ' . $condition);
}
@ -115,42 +152,59 @@ class Filter {
public function action() {
global $board;
switch($this->action) {
case 'reject':
error(isset($this->message) ? $this->message : 'Posting throttled by filter.');
case 'ban':
if (!isset($this->reason))
error('The ban action requires a reason.');
$this->add_note = isset($this->add_note) ? $this->add_note : false;
if ($this->add_note) {
$query = prepare('INSERT INTO ``ip_notes`` VALUES (NULL, :ip, :mod, :time, :body)');
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
$query->bindValue(':mod', -1);
$query->bindValue(':time', time());
$query->bindValue(':body', "Autoban message: ".$this->post['body']);
$query->execute() or error(db_error($query));
}
if (isset($this->action)) {
switch($this->action) {
case 'reject':
error(isset($this->message) ? $this->message : 'Posting throttled by filter.');
case 'ban':
if (!isset($this->reason)) {
error('The ban action requires a reason.');
}
$this->expires = isset($this->expires) ? $this->expires : false;
$this->reject = isset($this->reject) ? $this->reject : true;
$this->all_boards = isset($this->all_boards) ? $this->all_boards : false;
$this->expires = isset($this->expires) ? $this->expires : false;
$this->reject = isset($this->reject) ? $this->reject : true;
$this->all_boards = isset($this->all_boards) ? $this->all_boards : false;
Bans::new_ban($_SERVER['REMOTE_ADDR'], $this->reason, $this->expires, $this->all_boards ? false : $board['uri'], -1);
Bans::new_ban($_SERVER['REMOTE_ADDR'], $this->reason, $this->expires, $this->all_boards ? false : $board['uri'], -1);
if ($this->reject) {
if (isset($this->message))
error($message);
if ($this->reject) {
if (isset($this->message)) {
error($message);
}
checkBan($board['uri']);
exit;
}
checkBan($board['uri']);
exit;
}
break;
default:
error('Unknown filter action: ' . $this->action);
break;
default:
error('Unknown filter action: ' . $this->action);
}
}
}
public function check(array $post) {
$this->post = $post;
foreach ($this->condition as $condition => $value) {
if ($condition[0] == '!') {
$NOT = true;
$condition = substr($condition, 1);
} else $NOT = false;
} else {
$NOT = false;
}
if ($this->match($post, $condition, $value) == $NOT)
if ($this->match($condition, $value) == $NOT) {
return false;
}
}
return true;
}
@ -163,13 +217,14 @@ function purge_flood_table() {
// aware of flood filters in other board configurations. You can solve this problem by settings the
// config variable $config['flood_cache'] (seconds).
if (isset($config['flood_cache'])) {
if ($config['flood_cache'] != -1) {
$max_time = &$config['flood_cache'];
} else {
$max_time = 0;
foreach ($config['filters'] as $filter) {
if (isset($filter['condition']['flood-time']))
if (isset($filter['condition']['flood-time'])) {
$max_time = max($max_time, $filter['condition']['flood-time']);
}
}
}
@ -181,8 +236,9 @@ function purge_flood_table() {
function do_filters(array $post) {
global $config;
if (!isset($config['filters']) || empty($config['filters']))
if (!isset($config['filters']) || empty($config['filters'])) {
return;
}
foreach ($config['filters'] as $filter) {
if (isset($filter['condition']['flood-match'])) {
@ -211,10 +267,10 @@ function do_filters(array $post) {
foreach ($config['filters'] as $filter_array) {
$filter = new Filter($filter_array);
$filter->flood_check = $flood_check;
if ($filter->check($post))
if ($filter->check($post)) {
$filter->action();
}
}
purge_flood_table();
}

1690
inc/functions.php Normal file → Executable file

File diff suppressed because it is too large Load Diff

114
inc/functions/dice.php Normal file
View File

@ -0,0 +1,114 @@
<?php
namespace Vichan\Functions\Dice;
function _get_or_default_int(array $arr, int $index, int $default) {
return (isset($arr[$index]) && is_numeric($arr[$index])) ? (int)$arr[$index] : $default;
}
/* Die rolling:
* If "dice XdY+/-Z" is in the email field (where X or +/-Z may be
* missing), X Y-sided dice are rolled and summed, with the modifier Z
* added on. The result is displayed at the top of the post.
*/
function email_dice_roll($post) {
global $config;
if(strpos(strtolower($post->email), 'dice%20') === 0) {
$dicestr = str_split(substr($post->email, strlen('dice%20')));
// Get params
$diceX = '';
$diceY = '';
$diceZ = '';
$curd = 'diceX';
for($i = 0; $i < count($dicestr); $i ++) {
if(is_numeric($dicestr[$i])) {
$$curd .= $dicestr[$i];
} else if($dicestr[$i] == 'd') {
$curd = 'diceY';
} else if($dicestr[$i] == '-' || $dicestr[$i] == '+') {
$curd = 'diceZ';
$$curd = $dicestr[$i];
}
}
// Default values for X and Z
if($diceX == '') {
$diceX = '1';
}
if($diceZ == '') {
$diceZ = '+0';
}
// Intify them
$diceX = intval($diceX);
$diceY = intval($diceY);
$diceZ = intval($diceZ);
// Continue only if we have valid values
if($diceX > 0 && $diceY > 0) {
$dicerolls = array();
$dicesum = $diceZ;
for($i = 0; $i < $diceX; $i++) {
$roll = rand(1, $diceY);
$dicerolls[] = $roll;
$dicesum += $roll;
}
// Prepend the result to the post body
$modifier = ($diceZ != 0) ? ((($diceZ < 0) ? ' - ' : ' + ') . abs($diceZ)) : '';
$dicesum = ($diceX > 1) ? ' = ' . $dicesum : '';
$post->body = '<table class="diceroll"><tr><td><img src="'.$config['dir']['static'].'d10.svg" alt="Dice roll" width="24"></td><td>Rolled ' . implode(', ', $dicerolls) . $modifier . $dicesum . '</td></tr></table><br/>' . $post->body;
}
}
}
/**
* Rolls a dice and generates the appropriate html from the markup.
* @param array $matches The array of the matches according to the default configuration.
* 1 -> The number of dices to roll.
* 3 -> The number faces of the dices.
* 4 -> The offset to apply to the dice.
* @param string $img_path Path to the image to use relative to the root. Null if none.
* @return string The html to replace the original markup with.
*/
function inline_dice_roll_markup(array $matches, ?string $img_path): string {
global $config;
$dice_count = _get_or_default_int($matches, 1, 1);
$dice_faces = _get_or_default_int($matches, 3, 6);
$dice_offset = _get_or_default_int($matches, 4, 0);
// Clamp between 1 and max_roll_count.
$dice_count = max(min($dice_count, $config['max_roll_count']), 1);
// Must be at least 2.
if ($dice_faces < 2) {
$dice_faces = 6;
}
$tot = 0;
for ($i = 0; $i < $dice_count; $i++) {
$tot += mt_rand(1, $dice_faces);
}
// Ensure that final result is at least an integer.
$tot = abs((int)($dice_offset + $tot));
if ($img_path !== null) {
$img_text = "<img src='{$config['root']}{$img_path}' alt='dice' title='dice' class=\"inline-dice\"/>";
} else {
$img_text = '';
}
if ($dice_offset === 0) {
$dice_offset_text = '';
} elseif ($dice_offset > 0) {
$dice_offset_text = "+{$dice_offset}";
} else {
$dice_offset_text = (string)$dice_offset;
}
return "<span>$img_text {$dice_count}d{$dice_faces}{$dice_offset_text} = <b>$tot</b></span>";
}

28
inc/functions/format.php Normal file
View File

@ -0,0 +1,28 @@
<?php
namespace Vichan\Functions\Format;
function format_timestamp(int $delta): string {
switch (true) {
case $delta < 60:
return $delta . ' ' . ngettext('second', 'seconds', $delta);
case $delta < 3600: //60*60 = 3600
return ($num = round($delta/ 60)) . ' ' . ngettext('minute', 'minutes', $num);
case $delta < 86400: //60*60*24 = 86400
return ($num = round($delta / 3600)) . ' ' . ngettext('hour', 'hours', $num);
case $delta < 604800: //60*60*24*7 = 604800
return ($num = round($delta / 86400)) . ' ' . ngettext('day', 'days', $num);
case $delta < 31536000: //60*60*24*365 = 31536000
return ($num = round($delta / 604800)) . ' ' . ngettext('week', 'weeks', $num);
default:
return ($num = round($delta / 31536000)) . ' ' . ngettext('year', 'years', $num);
}
}
function until(int $timestamp): string {
return format_timestamp($timestamp - time());
}
function ago(int $timestamp): string {
return format_timestamp(time() - $timestamp);
}

16
inc/functions/net.php Normal file
View File

@ -0,0 +1,16 @@
<?php
namespace Vichan\Functions\Net;
/**
* @param bool $trust_headers. If true, trust the `HTTP_X_FORWARDED_PROTO` header to check if the connection is HTTPS.
* @return bool Returns if the client-server connection is an encrypted one (HTTPS).
*/
function is_connection_secure(bool $trust_headers): bool {
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
return true;
} elseif ($trust_headers && isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
return true;
}
return false;
}

33
inc/functions/num.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace Vichan\Functions\Num;
// Highest common factor
function hcf($a, $b){
$gcd = 1;
if ($a > $b) {
$a = $a+$b;
$b = $a-$b;
$a = $a-$b;
}
if ($b == (round($b / $a)) * $a) {
$gcd = $a;
} else {
for ($i = round($a / 2); $i; $i--) {
if ($a == round($a / $i) * $i && $b == round($b / $i) * $i) {
$gcd = $i;
$i = false;
}
}
}
return $gcd;
}
function fraction($numerator, $denominator, $sep) {
$gcf = hcf($numerator, $denominator);
$numerator = $numerator / $gcf;
$denominator = $denominator / $gcf;
return "{$numerator}{$sep}{$denominator}";
}

98
inc/functions/theme.php Normal file
View File

@ -0,0 +1,98 @@
<?php
namespace Vichan\Functions\Theme;
function rebuild_themes(string $action, $boardname = false): void {
global $config, $board, $current_locale;
// Save the global variables
$_config = $config;
$_board = $board;
// List themes
if ($themes = \Cache::get("themes")) {
// OK, we already have themes loaded
} else {
$query = query("SELECT `theme` FROM ``theme_settings`` WHERE `name` IS NULL AND `value` IS NULL") or error(db_error());
$themes = $query->fetchAll(\PDO::FETCH_NUM);
\Cache::set("themes", $themes);
}
foreach ($themes as $theme) {
// Restore them
$config = $_config;
$board = $_board;
// Reload the locale
if ($config['locale'] != $current_locale) {
$current_locale = $config['locale'];
init_locale($config['locale']);
}
if (PHP_SAPI === 'cli') {
echo "Rebuilding theme ".$theme[0]."... ";
}
rebuild_theme($theme[0], $action, $boardname);
if (PHP_SAPI === 'cli') {
echo "done\n";
}
}
// Restore them again
$config = $_config;
$board = $_board;
// Reload the locale
if ($config['locale'] != $current_locale) {
$current_locale = $config['locale'];
init_locale($config['locale']);
}
}
function load_theme_config($_theme) {
global $config;
if (!file_exists($config['dir']['themes'] . '/' . $_theme . '/info.php')) {
return false;
}
// Load theme information into $theme
include $config['dir']['themes'] . '/' . $_theme . '/info.php';
return $theme;
}
function rebuild_theme($theme, string $action, $board = false) {
global $config, $_theme;
$_theme = $theme;
$theme = load_theme_config($_theme);
if (file_exists($config['dir']['themes'] . '/' . $_theme . '/theme.php')) {
require_once $config['dir']['themes'] . '/' . $_theme . '/theme.php';
$theme['build_function']($action, theme_settings($_theme), $board);
}
}
function theme_settings($theme): array {
if ($settings = \Cache::get("theme_settings_" . $theme)) {
return $settings;
}
$query = prepare("SELECT `name`, `value` FROM ``theme_settings`` WHERE `theme` = :theme AND `name` IS NOT NULL");
$query->bindValue(':theme', $theme);
$query->execute() or error(db_error($query));
$settings = [];
while ($s = $query->fetch(\PDO::FETCH_ASSOC)) {
$settings[$s['name']] = $s['value'];
}
\Cache::set("theme_settings_".$theme, $settings);
return $settings;
}

View File

@ -291,6 +291,7 @@ class ImageConvert extends ImageBase {
} else {
rename($this->temp, $src);
chmod($src, 0664);
$this->temp = false;
}
}
public function width() {
@ -300,8 +301,10 @@ class ImageConvert extends ImageBase {
return $this->height;
}
public function destroy() {
@unlink($this->temp);
$this->temp = false;
if ($this->temp !== false) {
@unlink($this->temp);
$this->temp = false;
}
}
public function resize() {
global $config;
@ -311,7 +314,7 @@ class ImageConvert extends ImageBase {
$this->destroy();
}
$this->temp = tempnam($config['tmp'], 'convert');
$this->temp = tempnam($config['tmp'], 'convert') . ($config['thumb_ext'] == '' ? '' : '.' . $config['thumb_ext']);
$config['thumb_keep_animation_frames'] = (int)$config['thumb_keep_animation_frames'];
@ -324,12 +327,8 @@ class ImageConvert extends ImageBase {
error(_('Failed to resize image!'), null, $error);
}
} else {
if ($config['convert_manual_orient'] && ($this->format == 'jpg' || $this->format == 'jpeg'))
$convert_args = str_replace('-auto-orient', ImageConvert::jpeg_exif_orientation($this->src), $config['convert_args']);
elseif ($config['convert_manual_orient'])
$convert_args = str_replace('-auto-orient', '', $config['convert_args']);
else
$convert_args = &$config['convert_args'];
$convert_args = &$config['convert_args'];
if (($error = shell_exec_error(($this->gm ? 'gm ' : '') . 'convert ' .
sprintf($convert_args,
$this->width,
@ -347,12 +346,8 @@ class ImageConvert extends ImageBase {
}
}
} else {
if ($config['convert_manual_orient'] && ($this->format == 'jpg' || $this->format == 'jpeg'))
$convert_args = str_replace('-auto-orient', ImageConvert::jpeg_exif_orientation($this->src), $config['convert_args']);
elseif ($config['convert_manual_orient'])
$convert_args = str_replace('-auto-orient', '', $config['convert_args']);
else
$convert_args = &$config['convert_args'];
$convert_args = &$config['convert_args'];
if (($error = shell_exec_error(($this->gm ? 'gm ' : '') . 'convert ' .
sprintf($convert_args,
$this->width,
@ -361,10 +356,17 @@ class ImageConvert extends ImageBase {
$this->width,
$this->height,
escapeshellarg($this->temp)))) || !file_exists($this->temp)) {
if (!file_exists($this->temp)) {
$this->destroy();
error(_('Failed to resize image!'), null, $error);
}
if (strpos($error, "known incorrect sRGB profile") === false &&
strpos($error, "iCCP: Not recognizing known sRGB profile that has been edited") === false &&
strpos($error, "cHRM chunk does not match sRGB") === false) {
$this->destroy();
error(_('Failed to resize image!')." "._('Details: ').nl2br(htmlspecialchars($error)), null, array('convert_error' => $error));
}
if (!file_exists($this->temp)) {
$this->destroy();
error(_('Failed to resize image!'), null, $error);
}
}
if ($size = $this->get_size($this->temp)) {
$this->width = $size[0];
@ -372,69 +374,6 @@ class ImageConvert extends ImageBase {
}
}
}
// For when -auto-orient doesn't exist (older versions)
static public function jpeg_exif_orientation($src, $exif = false) {
if (!$exif) {
$exif = @exif_read_data($src);
if (!isset($exif['Orientation']))
return false;
}
switch($exif['Orientation']) {
case 1:
// Normal
return false;
case 2:
// 888888
// 88
// 8888
// 88
// 88
return '-flop';
case 3:
// 88
// 88
// 8888
// 88
// 888888
return '-flip -flop';
case 4:
// 88
// 88
// 8888
// 88
// 888888
return '-flip';
case 5:
// 8888888888
// 88 88
// 88
return '-rotate 90 -flop';
case 6:
// 88
// 88 88
// 8888888888
return '-rotate 90';
case 7:
// 88
// 88 88
// 8888888888
return '-rotate "-90" -flop';
case 8:
// 8888888888
// 88 88
// 88
return '-rotate "-90"';
}
}
}
class ImagePNG extends ImageBase {
@ -489,170 +428,11 @@ class ImageBMP extends ImageBase {
}
}
/*********************************************/
/* Fonction: imagecreatefrombmp */
/* Author: DHKold */
/* Contact: admin@dhkold.com */
/* Date: The 15th of June 2005 */
/* Version: 2.0B */
/*********************************************/
function imagecreatefrombmp($filename) {
if (! $f1 = fopen($filename,"rb")) return FALSE;
$FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
if ($FILE['file_type'] != 19778) return FALSE;
$BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
$BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
$BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
$BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
$BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] = 4-(4*$BMP['decal']);
if ($BMP['decal'] == 4) $BMP['decal'] = 0;
$PALETTE = array();
if ($BMP['colors'] < 16777216)
{
$PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
}
$IMG = fread($f1,$BMP['size_bitmap']);
$VIDE = chr(0);
$res = imagecreatetruecolor($BMP['width'],$BMP['height']);
$P = 0;
$Y = $BMP['height']-1;
while ($Y >= 0)
{
$X=0;
while ($X < $BMP['width'])
{
if ($BMP['bits_per_pixel'] == 24)
$COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
elseif ($BMP['bits_per_pixel'] == 16)
{
$COLOR = unpack("n",substr($IMG,$P,2));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 8)
{
$COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 4)
{
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 1)
{
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7;
elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
else
return FALSE;
imagesetpixel($res,$X,$Y,$COLOR[1]);
$X++;
$P += $BMP['bytes_per_pixel'];
class ImageWEBP extends ImageBase {
public function from() {
$this->image = @imagecreatefromwebp($this->src);
}
$Y--;
$P+=$BMP['decal'];
}
fclose($f1);
return $res;
}
function imagebmp(&$img, $filename='') {
$widthOrig = imagesx($img);
$widthFloor = ((floor($widthOrig/16))*16);
$widthCeil = ((ceil($widthOrig/16))*16);
$height = imagesy($img);
$size = ($widthCeil*$height*3)+54;
// Bitmap File Header
$result = 'BM'; // header (2b)
$result .= int_to_dword($size); // size of file (4b)
$result .= int_to_dword(0); // reserved (4b)
$result .= int_to_dword(54); // byte location in the file which is first byte of IMAGE (4b)
// Bitmap Info Header
$result .= int_to_dword(40); // Size of BITMAPINFOHEADER (4b)
$result .= int_to_dword($widthCeil); // width of bitmap (4b)
$result .= int_to_dword($height); // height of bitmap (4b)
$result .= int_to_word(1); // biPlanes = 1 (2b)
$result .= int_to_word(24); // biBitCount = {1 (mono) or 4 (16 clr ) or 8 (256 clr) or 24 (16 Mil)} (2b
$result .= int_to_dword(0); // RLE COMPRESSION (4b)
$result .= int_to_dword(0); // width x height (4b)
$result .= int_to_dword(0); // biXPelsPerMeter (4b)
$result .= int_to_dword(0); // biYPelsPerMeter (4b)
$result .= int_to_dword(0); // Number of palettes used (4b)
$result .= int_to_dword(0); // Number of important colour (4b)
// is faster than chr()
$arrChr = array();
for ($i=0; $i<256; $i++){
$arrChr[$i] = chr($i);
}
// creates image data
$bgfillcolor = array('red'=>0, 'green'=>0, 'blue'=>0);
// bottom to top - left to right - attention blue green red !!!
$y=$height-1;
for ($y2=0; $y2<$height; $y2++) {
for ($x=0; $x<$widthFloor; ) {
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
$rgb = imagecolorsforindex($img, imagecolorat($img, $x++, $y));
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
}
for ($x=$widthFloor; $x<$widthCeil; $x++) {
$rgb = ($x<$widthOrig) ? imagecolorsforindex($img, imagecolorat($img, $x, $y)) : $bgfillcolor;
$result .= $arrChr[$rgb['blue']].$arrChr[$rgb['green']].$arrChr[$rgb['red']];
}
$y--;
}
// see imagegif
if ($filename == '') {
echo $result;
} else {
$file = fopen($filename, 'wb');
fwrite($file, $result);
fclose($file);
public function to($src) {
imagewebp($this->image, $src);
}
}
// imagebmp helpers
function int_to_dword($n) {
return chr($n & 255).chr(($n >> 8) & 255).chr(($n >> 16) & 255).chr(($n >> 24) & 255);
}
function int_to_word($n) {
return chr($n & 255).chr(($n >> 8) & 255);
}

View File

@ -19,5 +19,5 @@
//$config['root'] = '/';
@include('inc/secrets.php');
?>

View File

@ -1,20 +0,0 @@
Copyright (c) 2013 Jason Morriss
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,293 +0,0 @@
<?php
/**
* This file is part of the Lifo\IP PHP Library.
*
* (c) Jason Morriss <lifo2013@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Lifo\IP;
/**
* BCMath helper class.
*
* Provides a handful of BCMath routines that are not included in the native
* PHP library.
*
* Note: The Bitwise functions operate on fixed byte boundaries. For example,
* comparing the following numbers uses X number of bits:
* 0xFFFF and 0xFF will result in comparison of 16 bits.
* 0xFFFFFFFF and 0xF will result in comparison of 32 bits.
* etc...
*
*/
abstract class BC
{
// Some common (maybe useless) constants
const MAX_INT_32 = '2147483647'; // 7FFFFFFF
const MAX_UINT_32 = '4294967295'; // FFFFFFFF
const MAX_INT_64 = '9223372036854775807'; // 7FFFFFFFFFFFFFFF
const MAX_UINT_64 = '18446744073709551615'; // FFFFFFFFFFFFFFFF
const MAX_INT_96 = '39614081257132168796771975167'; // 7FFFFFFFFFFFFFFFFFFFFFFF
const MAX_UINT_96 = '79228162514264337593543950335'; // FFFFFFFFFFFFFFFFFFFFFFFF
const MAX_INT_128 = '170141183460469231731687303715884105727'; // 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
const MAX_UINT_128 = '340282366920938463463374607431768211455'; // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
/**
* BC Math function to convert a HEX string into a DECIMAL
*/
public static function bchexdec($hex)
{
if (strlen($hex) == 1) {
return hexdec($hex);
}
$remain = substr($hex, 0, -1);
$last = substr($hex, -1);
return bcadd(bcmul(16, self::bchexdec($remain), 0), hexdec($last), 0);
}
/**
* BC Math function to convert a DECIMAL string into a BINARY string
*/
public static function bcdecbin($dec, $pad = null)
{
$bin = '';
while ($dec) {
$m = bcmod($dec, 2);
$dec = bcdiv($dec, 2, 0);
$bin = abs($m) . $bin;
}
return $pad ? sprintf("%0{$pad}s", $bin) : $bin;
}
/**
* BC Math function to convert a BINARY string into a DECIMAL string
*/
public static function bcbindec($bin)
{
$dec = '0';
for ($i=0, $j=strlen($bin); $i<$j; $i++) {
$dec = bcmul($dec, '2', 0);
$dec = bcadd($dec, $bin[$i], 0);
}
return $dec;
}
/**
* BC Math function to convert a BINARY string into a HEX string
*/
public static function bcbinhex($bin, $pad = 0)
{
return self::bcdechex(self::bcbindec($bin));
}
/**
* BC Math function to convert a DECIMAL into a HEX string
*/
public static function bcdechex($dec)
{
$last = bcmod($dec, 16);
$remain = bcdiv(bcsub($dec, $last, 0), 16, 0);
return $remain == 0 ? dechex($last) : self::bcdechex($remain) . dechex($last);
}
/**
* Bitwise AND two arbitrarily large numbers together.
*/
public static function bcand($left, $right)
{
$len = self::_bitwise($left, $right);
$value = '';
for ($i=0; $i<$len; $i++) {
$value .= (($left{$i} + 0) & ($right{$i} + 0)) ? '1' : '0';
}
return self::bcbindec($value != '' ? $value : '0');
}
/**
* Bitwise OR two arbitrarily large numbers together.
*/
public static function bcor($left, $right)
{
$len = self::_bitwise($left, $right);
$value = '';
for ($i=0; $i<$len; $i++) {
$value .= (($left{$i} + 0) | ($right{$i} + 0)) ? '1' : '0';
}
return self::bcbindec($value != '' ? $value : '0');
}
/**
* Bitwise XOR two arbitrarily large numbers together.
*/
public static function bcxor($left, $right)
{
$len = self::_bitwise($left, $right);
$value = '';
for ($i=0; $i<$len; $i++) {
$value .= (($left{$i} + 0) ^ ($right{$i} + 0)) ? '1' : '0';
}
return self::bcbindec($value != '' ? $value : '0');
}
/**
* Bitwise NOT two arbitrarily large numbers together.
*/
public static function bcnot($left, $bits = null)
{
$right = 0;
$len = self::_bitwise($left, $right, $bits);
$value = '';
for ($i=0; $i<$len; $i++) {
$value .= $left{$i} == '1' ? '0' : '1';
}
return self::bcbindec($value);
}
/**
* Shift number to the left
*
* @param integer $bits Total bits to shift
*/
public static function bcleft($num, $bits) {
return bcmul($num, bcpow('2', $bits));
}
/**
* Shift number to the right
*
* @param integer $bits Total bits to shift
*/
public static function bcright($num, $bits) {
return bcdiv($num, bcpow('2', $bits));
}
/**
* Determine how many bits are needed to store the number rounded to the
* nearest bit boundary.
*/
public static function bits_needed($num, $boundary = 4)
{
$bits = 0;
while ($num > 0) {
$num = bcdiv($num, '2', 0);
$bits++;
}
// round to nearest boundrary
return $boundary ? ceil($bits / $boundary) * $boundary : $bits;
}
/**
* BC Math function to return an arbitrarily large random number.
*/
public static function bcrand($min, $max = null)
{
if ($max === null) {
$max = $min;
$min = 0;
}
// swap values if $min > $max
if (bccomp($min, $max) == 1) {
list($min,$max) = array($max,$min);
}
return bcadd(
bcmul(
bcdiv(
mt_rand(0, mt_getrandmax()),
mt_getrandmax(),
strlen($max)
),
bcsub(
bcadd($max, '1'),
$min
)
),
$min
);
}
/**
* Computes the natural logarithm using a series.
* @author Thomas Oldbury.
* @license Public domain.
*/
public static function bclog($num, $iter = 10, $scale = 100)
{
$log = "0.0";
for($i = 0; $i < $iter; $i++) {
$pow = 1 + (2 * $i);
$mul = bcdiv("1.0", $pow, $scale);
$fraction = bcmul($mul, bcpow(bcsub($num, "1.0", $scale) / bcadd($num, "1.0", $scale), $pow, $scale), $scale);
$log = bcadd($fraction, $log, $scale);
}
return bcmul("2.0", $log, $scale);
}
/**
* Computes the base2 log using baseN log.
*/
public static function bclog2($num, $iter = 10, $scale = 100)
{
return bcdiv(self::bclog($num, $iter, $scale), self::bclog("2", $iter, $scale), $scale);
}
public static function bcfloor($num)
{
if (substr($num, 0, 1) == '-') {
return bcsub($num, 1, 0);
}
return bcadd($num, 0, 0);
}
public static function bcceil($num)
{
if (substr($num, 0, 1) == '-') {
return bcsub($num, 0, 0);
}
return bcadd($num, 1, 0);
}
/**
* Compare two numbers and return -1, 0, 1 depending if the LEFT number is
* < = > the RIGHT.
*
* @param string|integer $left Left side operand
* @param string|integer $right Right side operand
* @return integer Return -1,0,1 for <=> comparison
*/
public static function cmp($left, $right)
{
// @todo could an optimization be done to determine if a normal 32bit
// comparison could be done instead of using bccomp? But would
// the number verification cause too much overhead to be useful?
return bccomp($left, $right, 0);
}
/**
* Internal function to prepare for bitwise operations
*/
private static function _bitwise(&$left, &$right, $bits = null)
{
if ($bits === null) {
$bits = max(self::bits_needed($left), self::bits_needed($right));
}
$left = self::bcdecbin($left);
$right = self::bcdecbin($right);
$len = max(strlen($left), strlen($right), (int)$bits);
$left = sprintf("%0{$len}s", $left);
$right = sprintf("%0{$len}s", $right);
return $len;
}
}

View File

@ -1,706 +0,0 @@
<?php
/**
* This file is part of the Lifo\IP PHP Library.
*
* (c) Jason Morriss <lifo2013@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Lifo\IP;
/**
* CIDR Block helper class.
*
* Most routines can be used statically or by instantiating an object and
* calling its methods.
*
* Provides routines to do various calculations on IP addresses and ranges.
* Convert to/from CIDR to ranges, etc.
*/
class CIDR
{
const INTERSECT_NO = 0;
const INTERSECT_YES = 1;
const INTERSECT_LOW = 2;
const INTERSECT_HIGH = 3;
protected $start;
protected $end;
protected $prefix;
protected $version;
protected $istart;
protected $iend;
private $cache;
/**
* Create a new CIDR object.
*
* The IP range can be arbitrary and does not have to fall on a valid CIDR
* range. Some methods will return different values depending if you ignore
* the prefix or not. By default all prefix sensitive methods will assume
* the prefix is used.
*
* @param string $cidr An IP address (1.2.3.4), CIDR block (1.2.3.4/24),
* or range "1.2.3.4-1.2.3.10"
* @param string $end Ending IP in range if no cidr/prefix is given
*/
public function __construct($cidr, $end = null)
{
if ($end !== null) {
$this->setRange($cidr, $end);
} else {
$this->setCidr($cidr);
}
}
/**
* Returns the string representation of the CIDR block.
*/
public function __toString()
{
// do not include the prefix if its a single IP
try {
if ($this->isTrueCidr() && (
($this->version == 4 and $this->prefix != 32) ||
($this->version == 6 and $this->prefix != 128)
)
) {
return $this->start . '/' . $this->prefix;
}
} catch (\Exception $e) {
// isTrueCidr() calls getRange which can throw an exception
}
if (strcmp($this->start, $this->end) == 0) {
return $this->start;
}
return $this->start . ' - ' . $this->end;
}
public function __clone()
{
// do not clone the cache. No real reason why. I just want to keep the
// memory foot print as low as possible, even though this is trivial.
$this->cache = array();
}
/**
* Set an arbitrary IP range.
* The closest matching prefix will be calculated but the actual range
* stored in the object can be arbitrary.
* @param string $start Starting IP or combination "start-end" string.
* @param string $end Ending IP or null.
*/
public function setRange($ip, $end = null)
{
if (strpos($ip, '-') !== false) {
list($ip, $end) = array_map('trim', explode('-', $ip, 2));
}
if (false === filter_var($ip, FILTER_VALIDATE_IP) ||
false === filter_var($end, FILTER_VALIDATE_IP)) {
throw new \InvalidArgumentException("Invalid IP range \"$ip-$end\"");
}
// determine version (4 or 6)
$this->version = (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ? 6 : 4;
$this->istart = IP::inet_ptod($ip);
$this->iend = IP::inet_ptod($end);
// fix order
if (bccomp($this->istart, $this->iend) == 1) {
list($this->istart, $this->iend) = array($this->iend, $this->istart);
list($ip, $end) = array($end, $ip);
}
$this->start = $ip;
$this->end = $end;
// calculate real prefix
$len = $this->version == 4 ? 32 : 128;
$this->prefix = $len - strlen(BC::bcdecbin(BC::bcxor($this->istart, $this->iend)));
}
/**
* Returns true if the current IP is a true cidr block
*/
public function isTrueCidr()
{
return $this->start == $this->getNetwork() && $this->end == $this->getBroadcast();
}
/**
* Set the CIDR block.
*
* The prefix length is optional and will default to 32 ot 128 depending on
* the version detected.
*
* @param string $cidr CIDR block string, eg: "192.168.0.0/24" or "2001::1/64"
* @throws \InvalidArgumentException If the CIDR block is invalid
*/
public function setCidr($cidr)
{
if (strpos($cidr, '-') !== false) {
return $this->setRange($cidr);
}
list($ip, $bits) = array_pad(array_map('trim', explode('/', $cidr, 2)), 2, null);
if (false === filter_var($ip, FILTER_VALIDATE_IP)) {
throw new \InvalidArgumentException("Invalid IP address \"$cidr\"");
}
// determine version (4 or 6)
$this->version = (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ? 6 : 4;
$this->start = $ip;
$this->istart = IP::inet_ptod($ip);
if ($bits !== null and $bits !== '') {
$this->prefix = $bits;
} else {
$this->prefix = $this->version == 4 ? 32 : 128;
}
if (($this->prefix < 0)
|| ($this->prefix > 32 and $this->version == 4)
|| ($this->prefix > 128 and $this->version == 6)) {
throw new \InvalidArgumentException("Invalid IP address \"$cidr\"");
}
$this->end = $this->getBroadcast();
$this->iend = IP::inet_ptod($this->end);
$this->cache = array();
}
/**
* Get the IP version. 4 or 6.
*
* @return integer
*/
public function getVersion()
{
return $this->version;
}
/**
* Get the prefix.
*
* Always returns the "proper" prefix, even if the IP range is arbitrary.
*
* @return integer
*/
public function getPrefix()
{
return $this->prefix;
}
/**
* Return the starting presentational IP or Decimal value.
*
* Ignores prefix
*/
public function getStart($decimal = false)
{
return $decimal ? $this->istart : $this->start;
}
/**
* Return the ending presentational IP or Decimal value.
*
* Ignores prefix
*/
public function getEnd($decimal = false)
{
return $decimal ? $this->iend : $this->end;
}
/**
* Return the next presentational IP or Decimal value (following the
* broadcast address of the current CIDR block).
*/
public function getNext($decimal = false)
{
$next = bcadd($this->getEnd(true), '1');
return $decimal ? $next : new self(IP::inet_dtop($next));
}
/**
* Returns true if the IP is an IPv4
*
* @return boolean
*/
public function isIPv4()
{
return $this->version == 4;
}
/**
* Returns true if the IP is an IPv6
*
* @return boolean
*/
public function isIPv6()
{
return $this->version == 6;
}
/**
* Get the cidr notation for the subnet block.
*
* This is useful for when you want a string representation of the IP/prefix
* and the starting IP is not on a valid network boundrary (eg: Displaying
* an IP from an interface).
*
* @return string IP in CIDR notation "ipaddr/prefix"
*/
public function getCidr()
{
return $this->start . '/' . $this->prefix;
}
/**
* Get the [low,high] range of the CIDR block
*
* Prefix sensitive.
*
* @param boolean $ignorePrefix If true the arbitrary start-end range is
* returned. default=false.
*/
public function getRange($ignorePrefix = false)
{
$range = $ignorePrefix
? array($this->start, $this->end)
: self::cidr_to_range($this->start, $this->prefix);
// watch out for IP '0' being converted to IPv6 '::'
if ($range[0] == '::' and strpos($range[1], ':') == false) {
$range[0] = '0.0.0.0';
}
return $range;
}
/**
* Return the IP in its fully expanded form.
*
* For example: 2001::1 == 2007:0000:0000:0000:0000:0000:0000:0001
*
* @see IP::inet_expand
*/
public function getExpanded()
{
return IP::inet_expand($this->start);
}
/**
* Get network IP of the CIDR block
*
* Prefix sensitive.
*
* @param boolean $ignorePrefix If true the arbitrary start-end range is
* returned. default=false.
*/
public function getNetwork($ignorePrefix = false)
{
// micro-optimization to prevent calling getRange repeatedly
$k = $ignorePrefix ? 1 : 0;
if (!isset($this->cache['range'][$k])) {
$this->cache['range'][$k] = $this->getRange($ignorePrefix);
}
return $this->cache['range'][$k][0];
}
/**
* Get broadcast IP of the CIDR block
*
* Prefix sensitive.
*
* @param boolean $ignorePrefix If true the arbitrary start-end range is
* returned. default=false.
*/
public function getBroadcast($ignorePrefix = false)
{
// micro-optimization to prevent calling getRange repeatedly
$k = $ignorePrefix ? 1 : 0;
if (!isset($this->cache['range'][$k])) {
$this->cache['range'][$k] = $this->getRange($ignorePrefix);
}
return $this->cache['range'][$k][1];
}
/**
* Get the network mask based on the prefix.
*
*/
public function getMask()
{
return self::prefix_to_mask($this->prefix, $this->version);
}
/**
* Get total hosts within CIDR range
*
* Prefix sensitive.
*
* @param boolean $ignorePrefix If true the arbitrary start-end range is
* returned. default=false.
*/
public function getTotal($ignorePrefix = false)
{
// micro-optimization to prevent calling getRange repeatedly
$k = $ignorePrefix ? 1 : 0;
if (!isset($this->cache['range'][$k])) {
$this->cache['range'][$k] = $this->getRange($ignorePrefix);
}
return bcadd(bcsub(IP::inet_ptod($this->cache['range'][$k][1]),
IP::inet_ptod($this->cache['range'][$k][0])), '1');
}
public function intersects($cidr)
{
return self::cidr_intersect((string)$this, $cidr);
}
/**
* Determines the intersection between an IP (with optional prefix) and a
* CIDR block.
*
* The IP will be checked against the CIDR block given and will either be
* inside or outside the CIDR completely, or partially.
*
* NOTE: The caller should explicitly check against the INTERSECT_*
* constants because this method will return a value > 1 even for partial
* matches.
*
* @param mixed $ip The IP/cidr to match
* @param mixed $cidr The CIDR block to match within
* @return integer Returns an INTERSECT_* constant
* @throws \InvalidArgumentException if either $ip or $cidr is invalid
*/
public static function cidr_intersect($ip, $cidr)
{
// use fixed length HEX strings so we can easily do STRING comparisons
// instead of using slower bccomp() math.
list($lo,$hi) = array_map(function($v){ return sprintf("%032s", IP::inet_ptoh($v)); }, CIDR::cidr_to_range($ip));
list($min,$max) = array_map(function($v){ return sprintf("%032s", IP::inet_ptoh($v)); }, CIDR::cidr_to_range($cidr));
/** visualization of logic used below
lo-hi = $ip to check
min-max = $cidr block being checked against
--- --- --- lo --- --- hi --- --- --- --- --- IP/prefix to check
--- min --- --- max --- --- --- --- --- --- --- Partial "LOW" match
--- --- --- --- --- min --- --- max --- --- --- Partial "HIGH" match
--- --- --- --- min max --- --- --- --- --- --- No match "NO"
--- --- --- --- --- --- --- --- min --- max --- No match "NO"
min --- max --- --- --- --- --- --- --- --- --- No match "NO"
--- --- min --- --- --- --- max --- --- --- --- Full match "YES"
*/
// IP is exact match or completely inside the CIDR block
if ($lo >= $min and $hi <= $max) {
return self::INTERSECT_YES;
}
// IP is completely outside the CIDR block
if ($max < $lo or $min > $hi) {
return self::INTERSECT_NO;
}
// @todo is it useful to return LOW/HIGH partial matches?
// IP matches the lower end
if ($max <= $hi and $min <= $lo) {
return self::INTERSECT_LOW;
}
// IP matches the higher end
if ($min >= $lo and $max >= $hi) {
return self::INTERSECT_HIGH;
}
return self::INTERSECT_NO;
}
/**
* Converts an IPv4 or IPv6 CIDR block into its range.
*
* @todo May not be the fastest way to do this.
*
* @static
* @param string $cidr CIDR block or IP address string.
* @param integer|null $bits If /bits is not specified on string they can be
* passed via this parameter instead.
* @return array A 2 element array with the low, high range
*/
public static function cidr_to_range($cidr, $bits = null)
{
if (strpos($cidr, '/') !== false) {
list($ip, $_bits) = array_pad(explode('/', $cidr, 2), 2, null);
} else {
$ip = $cidr;
$_bits = $bits;
}
if (false === filter_var($ip, FILTER_VALIDATE_IP)) {
throw new \InvalidArgumentException("IP address \"$cidr\" is invalid");
}
// force bit length to 32 or 128 depending on type of IP
$bitlen = (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ? 128 : 32;
if ($bits === null) {
// if no prefix is given use the length of the binary string which
// will give us 32 or 128 and result in a single IP being returned.
$bits = $_bits !== null ? $_bits : $bitlen;
}
if ($bits > $bitlen) {
throw new \InvalidArgumentException("IP address \"$cidr\" is invalid");
}
$ipdec = IP::inet_ptod($ip);
$ipbin = BC::bcdecbin($ipdec, $bitlen);
// calculate network
$netmask = BC::bcbindec(str_pad(str_repeat('1',$bits), $bitlen, '0'));
$ip1 = BC::bcand($ipdec, $netmask);
// calculate "broadcast" (not technically a broadcast in IPv6)
$ip2 = BC::bcor($ip1, BC::bcnot($netmask));
return array(IP::inet_dtop($ip1), IP::inet_dtop($ip2));
}
/**
* Return the CIDR string from the range given
*/
public static function range_to_cidr($start, $end)
{
$cidr = new CIDR($start, $end);
return (string)$cidr;
}
/**
* Return the maximum prefix length that would fit the IP address given.
*
* This is useful to determine how my bit would be needed to store the IP
* address when you don't already have a prefix for the IP.
*
* @example 216.240.32.0 would return 27
*
* @param string $ip IP address without prefix
* @param integer $bits Maximum bits to check; defaults to 32 for IPv4 and 128 for IPv6
*/
public static function max_prefix($ip, $bits = null)
{
static $mask = array();
$ver = (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ? 6 : 4;
$max = $ver == 6 ? 128 : 32;
if ($bits === null) {
$bits = $max;
}
$int = IP::inet_ptod($ip);
while ($bits > 0) {
// micro-optimization; calculate mask once ...
if (!isset($mask[$ver][$bits-1])) {
// 2^$max - 2^($max - $bits);
if ($ver == 4) {
$mask[$ver][$bits-1] = pow(2, $max) - pow(2, $max - ($bits-1));
} else {
$mask[$ver][$bits-1] = bcsub(bcpow(2, $max), bcpow(2, $max - ($bits-1)));
}
}
$m = $mask[$ver][$bits-1];
//printf("%s/%d: %s & %s == %s\n", $ip, $bits-1, BC::bcdecbin($m, 32), BC::bcdecbin($int, 32), BC::bcdecbin(BC::bcand($int, $m)));
//echo "$ip/", $bits-1, ": ", IP::inet_dtop($m), " ($m) & $int == ", BC::bcand($int, $m), "\n";
if (bccomp(BC::bcand($int, $m), $int) != 0) {
return $bits;
}
$bits--;
}
return $bits;
}
/**
* Return a contiguous list of true CIDR blocks that span the range given.
*
* Note: It's not a good idea to call this with IPv6 addresses. While it may
* work for certain ranges this can be very slow. Also an IPv6 list won't be
* as accurate as an IPv4 list.
*
* @example
* range_to_cidrlist(192.168.0.0, 192.168.0.15) ==
* 192.168.0.0/28
* range_to_cidrlist(192.168.0.0, 192.168.0.20) ==
* 192.168.0.0/28
* 192.168.0.16/30
* 192.168.0.20/32
*/
public static function range_to_cidrlist($start, $end)
{
$ver = (false === filter_var($start, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ? 6 : 4;
$start = IP::inet_ptod($start);
$end = IP::inet_ptod($end);
$len = $ver == 4 ? 32 : 128;
$log2 = $ver == 4 ? log(2) : BC::bclog(2);
$list = array();
while (BC::cmp($end, $start) >= 0) { // $end >= $start
$prefix = self::max_prefix(IP::inet_dtop($start), $len);
if ($ver == 4) {
$diff = $len - floor( log($end - $start + 1) / $log2 );
} else {
// this is not as accurate due to the bclog function
$diff = bcsub($len, BC::bcfloor(bcdiv(BC::bclog(bcadd(bcsub($end, $start), '1')), $log2)));
}
if ($prefix < $diff) {
$prefix = $diff;
}
$list[] = IP::inet_dtop($start) . "/" . $prefix;
if ($ver == 4) {
$start += pow(2, $len - $prefix);
} else {
$start = bcadd($start, bcpow(2, $len - $prefix));
}
}
return $list;
}
/**
* Return an list of optimized CIDR blocks by collapsing adjacent CIDR
* blocks into larger blocks.
*
* @param array $cidrs List of CIDR block strings or objects
* @param integer $maxPrefix Maximum prefix to allow
* @return array Optimized list of CIDR objects
*/
public static function optimize_cidrlist($cidrs, $maxPrefix = 32)
{
// all indexes must be a CIDR object
$cidrs = array_map(function($o){ return $o instanceof CIDR ? $o : new CIDR($o); }, $cidrs);
// sort CIDR blocks in proper order so we can easily loop over them
$cidrs = self::cidr_sort($cidrs);
$list = array();
while ($cidrs) {
$c = array_shift($cidrs);
$start = $c->getStart();
$max = bcadd($c->getStart(true), $c->getTotal());
// loop through each cidr block until its ending range is more than
// the current maximum.
while (!empty($cidrs) and $cidrs[0]->getStart(true) <= $max) {
$b = array_shift($cidrs);
$newmax = bcadd($b->getStart(true), $b->getTotal());
if ($newmax > $max) {
$max = $newmax;
}
}
// add the new cidr range to the optimized list
$list = array_merge($list, self::range_to_cidrlist($start, IP::inet_dtop(bcsub($max, '1'))));
}
return $list;
}
/**
* Sort the list of CIDR blocks, optionally with a custom callback function.
*
* @param array $cidrs A list of CIDR blocks (strings or objects)
* @param Closure $callback Optional callback to perform the sorting.
* See PHP usort documentation for more details.
*/
public static function cidr_sort($cidrs, $callback = null)
{
// all indexes must be a CIDR object
$cidrs = array_map(function($o){ return $o instanceof CIDR ? $o : new CIDR($o); }, $cidrs);
if ($callback === null) {
$callback = function($a, $b) {
if (0 != ($o = BC::cmp($a->getStart(true), $b->getStart(true)))) {
return $o; // < or >
}
if ($a->getPrefix() == $b->getPrefix()) {
return 0;
}
return $a->getPrefix() < $b->getPrefix() ? -1 : 1;
};
} elseif (!($callback instanceof \Closure) or !is_callable($callback)) {
throw new \InvalidArgumentException("Invalid callback in CIDR::cidr_sort, expected Closure, got " . gettype($callback));
}
usort($cidrs, $callback);
return $cidrs;
}
/**
* Return the Prefix bits from the IPv4 mask given.
*
* This is only valid for IPv4 addresses since IPv6 addressing does not
* have a concept of network masks.
*
* Example: 255.255.255.0 == 24
*
* @param string $mask IPv4 network mask.
*/
public static function mask_to_prefix($mask)
{
if (false === filter_var($mask, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
throw new \InvalidArgumentException("Invalid IP netmask \"$mask\"");
}
return strrpos(IP::inet_ptob($mask, 32), '1') + 1;
}
/**
* Return the network mask for the prefix given.
*
* Normally this is only useful for IPv4 addresses but you can generate a
* mask for IPv6 addresses as well, only because its mathematically
* possible.
*
* @param integer $prefix CIDR prefix bits (0-128)
* @param integer $version IP version. If null the version will be detected
* based on the prefix length given.
*/
public static function prefix_to_mask($prefix, $version = null)
{
if ($version === null) {
$version = $prefix > 32 ? 6 : 4;
}
if ($prefix < 0 or $prefix > 128) {
throw new \InvalidArgumentException("Invalid prefix length \"$prefix\"");
}
if ($version != 4 and $version != 6) {
throw new \InvalidArgumentException("Invalid version \"$version\". Must be 4 or 6");
}
if ($version == 4) {
return long2ip($prefix == 0 ? 0 : (0xFFFFFFFF >> (32 - $prefix)) << (32 - $prefix));
} else {
return IP::inet_dtop($prefix == 0 ? 0 : BC::bcleft(BC::bcright(BC::MAX_UINT_128, 128-$prefix), 128-$prefix));
}
}
/**
* Return true if the $ip given is a true CIDR block.
*
* A true CIDR block is one where the $ip given is the actual Network
* address and broadcast matches the prefix appropriately.
*/
public static function cidr_is_true($ip)
{
$ip = new CIDR($ip);
return $ip->isTrueCidr();
}
}

View File

@ -1,207 +0,0 @@
<?php
/**
* This file is part of the Lifo\IP PHP Library.
*
* (c) Jason Morriss <lifo2013@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Lifo\IP;
/**
* IP Address helper class.
*
* Provides routines to translate IPv4 and IPv6 addresses between human readable
* strings, decimal, hexidecimal and binary.
*
* Requires BCmath extension and IPv6 PHP support
*/
abstract class IP
{
/**
* Convert a human readable (presentational) IP address string into a decimal string.
*/
public static function inet_ptod($ip)
{
// shortcut for IPv4 addresses
if (strpos($ip, ':') === false && strpos($ip, '.') !== false) {
return sprintf('%u', ip2long($ip));
}
// remove any cidr block notation
if (($o = strpos($ip, '/')) !== false) {
$ip = substr($ip, 0, $o);
}
// unpack into 4 32bit integers
$parts = unpack('N*', inet_pton($ip));
foreach ($parts as &$part) {
if ($part < 0) {
// convert signed int into unsigned
$part = sprintf('%u', $part);
//$part = bcadd($part, '4294967296');
}
}
// add each 32bit integer to the proper bit location in our big decimal
$decimal = $parts[4]; // << 0
$decimal = bcadd($decimal, bcmul($parts[3], '4294967296')); // << 32
$decimal = bcadd($decimal, bcmul($parts[2], '18446744073709551616')); // << 64
$decimal = bcadd($decimal, bcmul($parts[1], '79228162514264337593543950336')); // << 96
return $decimal;
}
/**
* Convert a decimal string into a human readable IP address.
*/
public static function inet_dtop($decimal, $expand = false)
{
$parts = array();
$parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0); // >> 96
$decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336'));
$parts[2] = bcdiv($decimal, '18446744073709551616', 0); // >> 64
$decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616'));
$parts[3] = bcdiv($decimal, '4294967296', 0); // >> 32
$decimal = bcsub($decimal, bcmul($parts[3], '4294967296'));
$parts[4] = $decimal; // >> 0
foreach ($parts as &$part) {
if (bccomp($part, '2147483647') == 1) {
$part = bcsub($part, '4294967296');
}
$part = (int) $part;
}
// if the first 96bits is all zeros then we can safely assume we
// actually have an IPv4 address. Even though it's technically possible
// you're not really ever going to see an IPv6 address in the range:
// ::0 - ::ffff
// It's feasible to see an IPv6 address of "::", in which case the
// caller is going to have to account for that on their own.
if (($parts[1] | $parts[2] | $parts[3]) == 0) {
$ip = long2ip($parts[4]);
} else {
$packed = pack('N4', $parts[1], $parts[2], $parts[3], $parts[4]);
$ip = inet_ntop($packed);
}
// Turn IPv6 to IPv4 if it's IPv4
if (preg_match('/^::\d+\./', $ip)) {
return substr($ip, 2);
}
return $expand ? self::inet_expand($ip) : $ip;
}
/**
* Convert a human readable (presentational) IP address into a HEX string.
*/
public static function inet_ptoh($ip)
{
return bin2hex(inet_pton($ip));
//return BC::bcdechex(self::inet_ptod($ip));
}
/**
* Convert a human readable (presentational) IP address into a BINARY string.
*/
public static function inet_ptob($ip, $bits = 128)
{
return BC::bcdecbin(self::inet_ptod($ip), $bits);
}
/**
* Convert a binary string into an IP address (presentational) string.
*/
public static function inet_btop($bin)
{
return self::inet_dtop(BC::bcbindec($bin));
}
/**
* Convert a HEX string into a human readable (presentational) IP address
*/
public static function inet_htop($hex)
{
return self::inet_dtop(BC::bchexdec($hex));
}
/**
* Expand an IP address. IPv4 addresses are returned as-is.
*
* Example:
* 2001::1 expands to 2001:0000:0000:0000:0000:0000:0000:0001
* ::127.0.0.1 expands to 0000:0000:0000:0000:0000:0000:7f00:0001
* 127.0.0.1 expands to 127.0.0.1
*/
public static function inet_expand($ip)
{
// strip possible cidr notation off
if (($pos = strpos($ip, '/')) !== false) {
$ip = substr($ip, 0, $pos);
}
$bytes = unpack('n*', inet_pton($ip));
if (count($bytes) > 2) {
return implode(':', array_map(function ($b) {
return sprintf("%04x", $b);
}, $bytes));
}
return $ip;
}
/**
* Convert an IPv4 address into an IPv6 address.
*
* One use-case for this is IP 6to4 tunnels used in networking.
*
* @example
* to_ipv4("10.10.10.10") == a0a:a0a
*
* @param string $ip IPv4 address.
* @param boolean $mapped If true a Full IPv6 address is returned within the
* official ipv4to6 mapped space "0:0:0:0:0:ffff:x:x"
*/
public static function to_ipv6($ip, $mapped = false)
{
if (!self::isIPv4($ip)) {
throw new \InvalidArgumentException("Invalid IPv4 address \"$ip\"");
}
$num = IP::inet_ptod($ip);
$o1 = dechex($num >> 16);
$o2 = dechex($num & 0x0000FFFF);
return $mapped ? "0:0:0:0:0:ffff:$o1:$o2" : "$o1:$o2";
}
/**
* Returns true if the IP address is a valid IPv4 address
*/
public static function isIPv4($ip)
{
return $ip === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
}
/**
* Returns true if the IP address is a valid IPv6 address
*/
public static function isIPv6($ip)
{
return $ip === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
}
/**
* Compare two IP's (v4 or v6) and return -1, 0, 1 if the first is < = >
* the second.
*
* @param string $ip1 IP address
* @param string $ip2 IP address to compare against
* @return integer Return -1,0,1 depending if $ip1 is <=> $ip2
*/
public static function cmp($ip1, $ip2)
{
return bccomp(self::inet_ptod($ip1), self::inet_ptod($ip2), 0);
}
}

View File

@ -1,48 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Autoloads Twig classes.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Autoloader
{
/**
* Registers Twig_Autoloader as an SPL autoloader.
*
* @param Boolean $prepend Whether to prepend the autoloader or not.
*/
public static function register($prepend = false)
{
if (version_compare(phpversion(), '5.3.0', '>=')) {
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
} else {
spl_autoload_register(array(new self, 'autoload'));
}
}
/**
* Handles autoloading of classes.
*
* @param string $class A class name.
*/
public static function autoload($class)
{
if (0 !== strpos($class, 'Twig')) {
return;
}
if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
require $file;
}
}
}

View File

@ -1,268 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Compiles a node to PHP code.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Compiler implements Twig_CompilerInterface
{
protected $lastLine;
protected $source;
protected $indentation;
protected $env;
protected $debugInfo;
protected $sourceOffset;
protected $sourceLine;
protected $filename;
/**
* Constructor.
*
* @param Twig_Environment $env The twig environment instance
*/
public function __construct(Twig_Environment $env)
{
$this->env = $env;
$this->debugInfo = array();
}
public function getFilename()
{
return $this->filename;
}
/**
* Returns the environment instance related to this compiler.
*
* @return Twig_Environment The environment instance
*/
public function getEnvironment()
{
return $this->env;
}
/**
* Gets the current PHP code after compilation.
*
* @return string The PHP code
*/
public function getSource()
{
return $this->source;
}
/**
* Compiles a node.
*
* @param Twig_NodeInterface $node The node to compile
* @param integer $indentation The current indentation
*
* @return Twig_Compiler The current compiler instance
*/
public function compile(Twig_NodeInterface $node, $indentation = 0)
{
$this->lastLine = null;
$this->source = '';
$this->sourceOffset = 0;
// source code starts at 1 (as we then increment it when we encounter new lines)
$this->sourceLine = 1;
$this->indentation = $indentation;
if ($node instanceof Twig_Node_Module) {
$this->filename = $node->getAttribute('filename');
}
$node->compile($this);
return $this;
}
public function subcompile(Twig_NodeInterface $node, $raw = true)
{
if (false === $raw) {
$this->addIndentation();
}
$node->compile($this);
return $this;
}
/**
* Adds a raw string to the compiled code.
*
* @param string $string The string
*
* @return Twig_Compiler The current compiler instance
*/
public function raw($string)
{
$this->source .= $string;
return $this;
}
/**
* Writes a string to the compiled code by adding indentation.
*
* @return Twig_Compiler The current compiler instance
*/
public function write()
{
$strings = func_get_args();
foreach ($strings as $string) {
$this->addIndentation();
$this->source .= $string;
}
return $this;
}
/**
* Appends an indentation to the current PHP code after compilation.
*
* @return Twig_Compiler The current compiler instance
*/
public function addIndentation()
{
$this->source .= str_repeat(' ', $this->indentation * 4);
return $this;
}
/**
* Adds a quoted string to the compiled code.
*
* @param string $value The string
*
* @return Twig_Compiler The current compiler instance
*/
public function string($value)
{
$this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
return $this;
}
/**
* Returns a PHP representation of a given value.
*
* @param mixed $value The value to convert
*
* @return Twig_Compiler The current compiler instance
*/
public function repr($value)
{
if (is_int($value) || is_float($value)) {
if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
setlocale(LC_NUMERIC, 'C');
}
$this->raw($value);
if (false !== $locale) {
setlocale(LC_NUMERIC, $locale);
}
} elseif (null === $value) {
$this->raw('null');
} elseif (is_bool($value)) {
$this->raw($value ? 'true' : 'false');
} elseif (is_array($value)) {
$this->raw('array(');
$first = true;
foreach ($value as $key => $value) {
if (!$first) {
$this->raw(', ');
}
$first = false;
$this->repr($key);
$this->raw(' => ');
$this->repr($value);
}
$this->raw(')');
} else {
$this->string($value);
}
return $this;
}
/**
* Adds debugging information.
*
* @param Twig_NodeInterface $node The related twig node
*
* @return Twig_Compiler The current compiler instance
*/
public function addDebugInfo(Twig_NodeInterface $node)
{
if ($node->getLine() != $this->lastLine) {
$this->write("// line {$node->getLine()}\n");
// when mbstring.func_overload is set to 2
// mb_substr_count() replaces substr_count()
// but they have different signatures!
if (((int) ini_get('mbstring.func_overload')) & 2) {
// this is much slower than the "right" version
$this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
} else {
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
}
$this->sourceOffset = strlen($this->source);
$this->debugInfo[$this->sourceLine] = $node->getLine();
$this->lastLine = $node->getLine();
}
return $this;
}
public function getDebugInfo()
{
return $this->debugInfo;
}
/**
* Indents the generated code.
*
* @param integer $step The number of indentation to add
*
* @return Twig_Compiler The current compiler instance
*/
public function indent($step = 1)
{
$this->indentation += $step;
return $this;
}
/**
* Outdents the generated code.
*
* @param integer $step The number of indentation to remove
*
* @return Twig_Compiler The current compiler instance
*/
public function outdent($step = 1)
{
// can't outdent by more steps than the current indentation level
if ($this->indentation < $step) {
throw new LogicException('Unable to call outdent() as the indentation would become negative');
}
$this->indentation -= $step;
return $this;
}
}

View File

@ -1,35 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Interface implemented by compiler classes.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
interface Twig_CompilerInterface
{
/**
* Compiles a node.
*
* @param Twig_NodeInterface $node The node to compile
*
* @return Twig_CompilerInterface The current compiler instance
*/
public function compile(Twig_NodeInterface $node);
/**
* Gets the current PHP code after compilation.
*
* @return string The PHP code
*/
public function getSource();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,243 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Twig base exception.
*
* This exception class and its children must only be used when
* an error occurs during the loading of a template, when a syntax error
* is detected in a template, or when rendering a template. Other
* errors must use regular PHP exception classes (like when the template
* cache directory is not writable for instance).
*
* To help debugging template issues, this class tracks the original template
* name and line where the error occurred.
*
* Whenever possible, you must set these information (original template name
* and line number) yourself by passing them to the constructor. If some or all
* these information are not available from where you throw the exception, then
* this class will guess them automatically (when the line number is set to -1
* and/or the filename is set to null). As this is a costly operation, this
* can be disabled by passing false for both the filename and the line number
* when creating a new instance of this class.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Error extends Exception
{
protected $lineno;
protected $filename;
protected $rawMessage;
protected $previous;
/**
* Constructor.
*
* Set both the line number and the filename to false to
* disable automatic guessing of the original template name
* and line number.
*
* Set the line number to -1 to enable its automatic guessing.
* Set the filename to null to enable its automatic guessing.
*
* By default, automatic guessing is enabled.
*
* @param string $message The error message
* @param integer $lineno The template line where the error occurred
* @param string $filename The template file name where the error occurred
* @param Exception $previous The previous exception
*/
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
{
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
$this->previous = $previous;
parent::__construct('');
} else {
parent::__construct('', 0, $previous);
}
$this->lineno = $lineno;
$this->filename = $filename;
if (-1 === $this->lineno || null === $this->filename) {
$this->guessTemplateInfo();
}
$this->rawMessage = $message;
$this->updateRepr();
}
/**
* Gets the raw message.
*
* @return string The raw message
*/
public function getRawMessage()
{
return $this->rawMessage;
}
/**
* Gets the filename where the error occurred.
*
* @return string The filename
*/
public function getTemplateFile()
{
return $this->filename;
}
/**
* Sets the filename where the error occurred.
*
* @param string $filename The filename
*/
public function setTemplateFile($filename)
{
$this->filename = $filename;
$this->updateRepr();
}
/**
* Gets the template line where the error occurred.
*
* @return integer The template line
*/
public function getTemplateLine()
{
return $this->lineno;
}
/**
* Sets the template line where the error occurred.
*
* @param integer $lineno The template line
*/
public function setTemplateLine($lineno)
{
$this->lineno = $lineno;
$this->updateRepr();
}
public function guess()
{
$this->guessTemplateInfo();
$this->updateRepr();
}
/**
* For PHP < 5.3.0, provides access to the getPrevious() method.
*
* @param string $method The method name
* @param array $arguments The parameters to be passed to the method
*
* @return Exception The previous exception or null
*
* @throws BadMethodCallException
*/
public function __call($method, $arguments)
{
if ('getprevious' == strtolower($method)) {
return $this->previous;
}
throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
}
protected function updateRepr()
{
$this->message = $this->rawMessage;
$dot = false;
if ('.' === substr($this->message, -1)) {
$this->message = substr($this->message, 0, -1);
$dot = true;
}
if ($this->filename) {
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
$filename = sprintf('"%s"', $this->filename);
} else {
$filename = json_encode($this->filename);
}
$this->message .= sprintf(' in %s', $filename);
}
if ($this->lineno && $this->lineno >= 0) {
$this->message .= sprintf(' at line %d', $this->lineno);
}
if ($dot) {
$this->message .= '.';
}
}
protected function guessTemplateInfo()
{
$template = null;
$templateClass = null;
if (version_compare(phpversion(), '5.3.6', '>=')) {
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
} else {
$backtrace = debug_backtrace();
}
foreach ($backtrace as $trace) {
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
$currentClass = get_class($trace['object']);
$isEmbedContainer = 0 === strpos($templateClass, $currentClass);
if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
$template = $trace['object'];
$templateClass = get_class($trace['object']);
}
}
}
// update template filename
if (null !== $template && null === $this->filename) {
$this->filename = $template->getTemplateName();
}
if (null === $template || $this->lineno > -1) {
return;
}
$r = new ReflectionObject($template);
$file = $r->getFileName();
$exceptions = array($e = $this);
while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
$exceptions[] = $e;
}
while ($e = array_pop($exceptions)) {
$traces = $e->getTrace();
while ($trace = array_shift($traces)) {
if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
continue;
}
foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
if ($codeLine <= $trace['line']) {
// update template line
$this->lineno = $templateLine;
return;
}
}
}
}
}
}

View File

@ -1,31 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception thrown when an error occurs during template loading.
*
* Automatic template information guessing is always turned off as
* if a template cannot be loaded, there is nothing to guess.
* However, when a template is loaded from another one, then, we need
* to find the current context and this is automatically done by
* Twig_Template::displayWithErrorHandling().
*
* This strategy makes Twig_Environment::resolveTemplate() much faster.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Error_Loader extends Twig_Error
{
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
{
parent::__construct($message, false, false, $previous);
}
}

View File

@ -1,20 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception thrown when an error occurs at runtime.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Error_Runtime extends Twig_Error
{
}

View File

@ -1,20 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception thrown when a syntax error occurs during lexing or parsing of a template.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Error_Syntax extends Twig_Error
{
}

View File

@ -1,28 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Adds an exists() method for loaders.
*
* @author Florin Patan <florinpatan@gmail.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
interface Twig_ExistsLoaderInterface
{
/**
* Check if we have the source code of a template, given its name.
*
* @param string $name The name of the template to check if we can load
*
* @return boolean If the template source code is handled by this loader or not
*/
public function exists($name);
}

View File

@ -1,611 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Parses expressions.
*
* This parser implements a "Precedence climbing" algorithm.
*
* @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_ExpressionParser
{
const OPERATOR_LEFT = 1;
const OPERATOR_RIGHT = 2;
protected $parser;
protected $unaryOperators;
protected $binaryOperators;
public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
{
$this->parser = $parser;
$this->unaryOperators = $unaryOperators;
$this->binaryOperators = $binaryOperators;
}
public function parseExpression($precedence = 0)
{
$expr = $this->getPrimary();
$token = $this->parser->getCurrentToken();
while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
$op = $this->binaryOperators[$token->getValue()];
$this->parser->getStream()->next();
if (isset($op['callable'])) {
$expr = call_user_func($op['callable'], $this->parser, $expr);
} else {
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
$class = $op['class'];
$expr = new $class($expr, $expr1, $token->getLine());
}
$token = $this->parser->getCurrentToken();
}
if (0 === $precedence) {
return $this->parseConditionalExpression($expr);
}
return $expr;
}
protected function getPrimary()
{
$token = $this->parser->getCurrentToken();
if ($this->isUnary($token)) {
$operator = $this->unaryOperators[$token->getValue()];
$this->parser->getStream()->next();
$expr = $this->parseExpression($operator['precedence']);
$class = $operator['class'];
return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$this->parser->getStream()->next();
$expr = $this->parseExpression();
$this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
return $this->parsePostfixExpression($expr);
}
return $this->parsePrimaryExpression();
}
protected function parseConditionalExpression($expr)
{
while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
$this->parser->getStream()->next();
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
$expr2 = $this->parseExpression();
if ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
$this->parser->getStream()->next();
$expr3 = $this->parseExpression();
} else {
$expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
}
} else {
$this->parser->getStream()->next();
$expr2 = $expr;
$expr3 = $this->parseExpression();
}
$expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
}
return $expr;
}
protected function isUnary(Twig_Token $token)
{
return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
}
protected function isBinary(Twig_Token $token)
{
return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
}
public function parsePrimaryExpression()
{
$token = $this->parser->getCurrentToken();
switch ($token->getType()) {
case Twig_Token::NAME_TYPE:
$this->parser->getStream()->next();
switch ($token->getValue()) {
case 'true':
case 'TRUE':
$node = new Twig_Node_Expression_Constant(true, $token->getLine());
break;
case 'false':
case 'FALSE':
$node = new Twig_Node_Expression_Constant(false, $token->getLine());
break;
case 'none':
case 'NONE':
case 'null':
case 'NULL':
$node = new Twig_Node_Expression_Constant(null, $token->getLine());
break;
default:
if ('(' === $this->parser->getCurrentToken()->getValue()) {
$node = $this->getFunctionNode($token->getValue(), $token->getLine());
} else {
$node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
}
}
break;
case Twig_Token::NUMBER_TYPE:
$this->parser->getStream()->next();
$node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
break;
case Twig_Token::STRING_TYPE:
case Twig_Token::INTERPOLATION_START_TYPE:
$node = $this->parseStringExpression();
break;
default:
if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
$node = $this->parseArrayExpression();
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
$node = $this->parseHashExpression();
} else {
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine(), $this->parser->getFilename());
}
}
return $this->parsePostfixExpression($node);
}
public function parseStringExpression()
{
$stream = $this->parser->getStream();
$nodes = array();
// a string cannot be followed by another string in a single expression
$nextCanBeString = true;
while (true) {
if ($stream->test(Twig_Token::STRING_TYPE) && $nextCanBeString) {
$token = $stream->next();
$nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
$nextCanBeString = false;
} elseif ($stream->test(Twig_Token::INTERPOLATION_START_TYPE)) {
$stream->next();
$nodes[] = $this->parseExpression();
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
$nextCanBeString = true;
} else {
break;
}
}
$expr = array_shift($nodes);
foreach ($nodes as $node) {
$expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine());
}
return $expr;
}
public function parseArrayExpression()
{
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
$node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
$first = true;
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
if (!$first) {
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
// trailing ,?
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
break;
}
}
$first = false;
$node->addElement($this->parseExpression());
}
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
return $node;
}
public function parseHashExpression()
{
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
$node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
$first = true;
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
if (!$first) {
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
// trailing ,?
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
break;
}
}
$first = false;
// a hash key can be:
//
// * a number -- 12
// * a string -- 'a'
// * a name, which is equivalent to a string -- a
// * an expression, which must be enclosed in parentheses -- (1 + 2)
if ($stream->test(Twig_Token::STRING_TYPE) || $stream->test(Twig_Token::NAME_TYPE) || $stream->test(Twig_Token::NUMBER_TYPE)) {
$token = $stream->next();
$key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
} elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$key = $this->parseExpression();
} else {
$current = $stream->getCurrent();
throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine(), $this->parser->getFilename());
}
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
$value = $this->parseExpression();
$node->addElement($value, $key);
}
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
return $node;
}
public function parsePostfixExpression($node)
{
while (true) {
$token = $this->parser->getCurrentToken();
if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
if ('.' == $token->getValue() || '[' == $token->getValue()) {
$node = $this->parseSubscriptExpression($node);
} elseif ('|' == $token->getValue()) {
$node = $this->parseFilterExpression($node);
} else {
break;
}
} else {
break;
}
}
return $node;
}
public function getFunctionNode($name, $line)
{
switch ($name) {
case 'parent':
$args = $this->parseArguments();
if (!count($this->parser->getBlockStack())) {
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
}
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename());
}
return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
case 'block':
return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line);
case 'attribute':
$args = $this->parseArguments();
if (count($args) < 2) {
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
}
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line);
default:
$args = $this->parseArguments(true);
if (null !== $alias = $this->parser->getImportedSymbol('macro', $name)) {
return new Twig_Node_Expression_MacroCall($alias['node'], $alias['name'], $this->createArrayFromArguments($args), $line);
}
try {
$class = $this->getFunctionNodeClass($name, $line);
} catch (Twig_Error_Syntax $e) {
if (!$this->parser->hasMacro($name)) {
throw $e;
}
return new Twig_Node_Expression_MacroCall(new Twig_Node_Expression_Name('_self', $line), $name, $this->createArrayFromArguments($args), $line);
}
return new $class($name, $args, $line);
}
}
public function parseSubscriptExpression($node)
{
$stream = $this->parser->getStream();
$token = $stream->next();
$lineno = $token->getLine();
$arguments = new Twig_Node_Expression_Array(array(), $lineno);
$type = Twig_Template::ANY_CALL;
if ($token->getValue() == '.') {
$token = $stream->next();
if (
$token->getType() == Twig_Token::NAME_TYPE
||
$token->getType() == Twig_Token::NUMBER_TYPE
||
($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
) {
$arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
} else {
throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
}
if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
if (!$arg instanceof Twig_Node_Expression_Constant) {
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
}
$arguments = $this->createArrayFromArguments($this->parseArguments(true));
return new Twig_Node_Expression_MacroCall($node, $arg->getAttribute('value'), $arguments, $lineno);
}
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$type = Twig_Template::METHOD_CALL;
$arguments = $this->createArrayFromArguments($this->parseArguments());
}
} else {
$type = Twig_Template::ARRAY_CALL;
// slice?
$slice = false;
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
$slice = true;
$arg = new Twig_Node_Expression_Constant(0, $token->getLine());
} else {
$arg = $this->parseExpression();
}
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
$slice = true;
$stream->next();
}
if ($slice) {
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
$length = new Twig_Node_Expression_Constant(null, $token->getLine());
} else {
$length = $this->parseExpression();
}
$class = $this->getFilterNodeClass('slice', $token->getLine());
$arguments = new Twig_Node(array($arg, $length));
$filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
return $filter;
}
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
}
return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
}
public function parseFilterExpression($node)
{
$this->parser->getStream()->next();
return $this->parseFilterExpressionRaw($node);
}
public function parseFilterExpressionRaw($node, $tag = null)
{
while (true) {
$token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE);
$name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$arguments = new Twig_Node();
} else {
$arguments = $this->parseArguments(true);
}
$class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());
$node = new $class($node, $name, $arguments, $token->getLine(), $tag);
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
break;
}
$this->parser->getStream()->next();
}
return $node;
}
/**
* Parses arguments.
*
* @param Boolean $namedArguments Whether to allow named arguments or not
* @param Boolean $definition Whether we are parsing arguments for a function definition
*
* @return Twig_Node
*/
public function parseArguments($namedArguments = false, $definition = false)
{
$args = array();
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
if (!empty($args)) {
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
}
if ($definition) {
$token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name');
$value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine());
} else {
$value = $this->parseExpression();
}
$name = null;
if ($namedArguments && $stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
$token = $stream->next();
if (!$value instanceof Twig_Node_Expression_Name) {
throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
}
$name = $value->getAttribute('name');
if ($definition) {
$value = $this->parsePrimaryExpression();
if (!$this->checkConstantExpression($value)) {
throw new Twig_Error_Syntax('A default value for an argument must be a constant (a boolean, a string, a number, or an array).', $token->getLine(), $this->parser->getFilename());
}
} else {
$value = $this->parseExpression();
}
}
if ($definition && null === $name) {
$name = $value->getAttribute('name');
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
}
if (null === $name) {
$args[] = $value;
} else {
if ($definition && isset($args[$name])) {
throw new Twig_Error_Syntax(sprintf('Arguments cannot contain the same argument name more than once ("%s" is defined twice).', $name), $token->getLine(), $this->parser->getFilename());
}
$args[$name] = $value;
}
}
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
return new Twig_Node($args);
}
public function parseAssignmentExpression()
{
$targets = array();
while (true) {
$token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
if (in_array($token->getValue(), array('true', 'false', 'none'))) {
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
}
$targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
break;
}
$this->parser->getStream()->next();
}
return new Twig_Node($targets);
}
public function parseMultitargetExpression()
{
$targets = array();
while (true) {
$targets[] = $this->parseExpression();
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
break;
}
$this->parser->getStream()->next();
}
return new Twig_Node($targets);
}
protected function getFunctionNodeClass($name, $line)
{
$env = $this->parser->getEnvironment();
if (false === $function = $env->getFunction($name)) {
$message = sprintf('The function "%s" does not exist', $name);
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) {
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
}
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
}
if ($function instanceof Twig_SimpleFunction) {
return $function->getNodeClass();
}
return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function';
}
protected function getFilterNodeClass($name, $line)
{
$env = $this->parser->getEnvironment();
if (false === $filter = $env->getFilter($name)) {
$message = sprintf('The filter "%s" does not exist', $name);
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) {
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
}
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
}
if ($filter instanceof Twig_SimpleFilter) {
return $filter->getNodeClass();
}
return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter';
}
// checks that the node only contains "constant" elements
protected function checkConstantExpression(Twig_NodeInterface $node)
{
if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
return false;
}
foreach ($node as $n) {
if (!$this->checkConstantExpression($n)) {
return false;
}
}
return true;
}
private function createArrayFromArguments(Twig_Node $arguments, $line = null)
{
$line = null === $line ? $arguments->getLine() : $line;
$array = new Twig_Node_Expression_Array(array(), $line);
foreach ($arguments as $key => $value) {
$array->addElement($value, new Twig_Node_Expression_Constant($key, $value->getLine()));
}
return $array;
}
}

View File

@ -1,93 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
abstract class Twig_Extension implements Twig_ExtensionInterface
{
/**
* Initializes the runtime environment.
*
* This is where you can load some file that contains filter functions for instance.
*
* @param Twig_Environment $environment The current Twig_Environment instance
*/
public function initRuntime(Twig_Environment $environment)
{
}
/**
* Returns the token parser instances to add to the existing list.
*
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
*/
public function getTokenParsers()
{
return array();
}
/**
* Returns the node visitor instances to add to the existing list.
*
* @return array An array of Twig_NodeVisitorInterface instances
*/
public function getNodeVisitors()
{
return array();
}
/**
* Returns a list of filters to add to the existing list.
*
* @return array An array of filters
*/
public function getFilters()
{
return array();
}
/**
* Returns a list of tests to add to the existing list.
*
* @return array An array of tests
*/
public function getTests()
{
return array();
}
/**
* Returns a list of functions to add to the existing list.
*
* @return array An array of functions
*/
public function getFunctions()
{
return array();
}
/**
* Returns a list of operators to add to the existing list.
*
* @return array An array of operators
*/
public function getOperators()
{
return array();
}
/**
* Returns a list of global variables to add to the existing list.
*
* @return array An array of global variables
*/
public function getGlobals()
{
return array();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2011 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extension_Debug extends Twig_Extension
{
/**
* Returns a list of global functions to add to the existing list.
*
* @return array An array of global functions
*/
public function getFunctions()
{
// dump is safe if var_dump is overridden by xdebug
$isDumpOutputHtmlSafe = extension_loaded('xdebug')
// false means that it was not set (and the default is on) or it explicitly enabled
&& (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
// false means that it was not set (and the default is on) or it explicitly enabled
// xdebug.overload_var_dump produces HTML only when html_errors is also enabled
&& (false === ini_get('html_errors') || ini_get('html_errors'))
|| 'cli' === php_sapi_name()
;
return array(
new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
);
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'debug';
}
}
function twig_var_dump(Twig_Environment $env, $context)
{
if (!$env->isDebug()) {
return;
}
ob_start();
$count = func_num_args();
if (2 === $count) {
$vars = array();
foreach ($context as $key => $value) {
if (!$value instanceof Twig_Template) {
$vars[$key] = $value;
}
}
var_dump($vars);
} else {
for ($i = 2; $i < $count; $i++) {
var_dump(func_get_arg($i));
}
}
return ob_get_clean();
}

View File

@ -1,107 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extension_Escaper extends Twig_Extension
{
protected $defaultStrategy;
public function __construct($defaultStrategy = 'html')
{
$this->setDefaultStrategy($defaultStrategy);
}
/**
* Returns the token parser instances to add to the existing list.
*
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
*/
public function getTokenParsers()
{
return array(new Twig_TokenParser_AutoEscape());
}
/**
* Returns the node visitor instances to add to the existing list.
*
* @return array An array of Twig_NodeVisitorInterface instances
*/
public function getNodeVisitors()
{
return array(new Twig_NodeVisitor_Escaper());
}
/**
* Returns a list of filters to add to the existing list.
*
* @return array An array of filters
*/
public function getFilters()
{
return array(
new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))),
);
}
/**
* Sets the default strategy to use when not defined by the user.
*
* The strategy can be a valid PHP callback that takes the template
* "filename" as an argument and returns the strategy to use.
*
* @param mixed $defaultStrategy An escaping strategy
*/
public function setDefaultStrategy($defaultStrategy)
{
// for BC
if (true === $defaultStrategy) {
$defaultStrategy = 'html';
}
$this->defaultStrategy = $defaultStrategy;
}
/**
* Gets the default strategy to use when not defined by the user.
*
* @param string $filename The template "filename"
*
* @return string The default strategy to use for the template
*/
public function getDefaultStrategy($filename)
{
// disable string callables to avoid calling a function named html or js,
// or any other upcoming escaping strategy
if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) {
return call_user_func($this->defaultStrategy, $filename);
}
return $this->defaultStrategy;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'escaper';
}
}
/**
* Marks a variable as being safe.
*
* @param string $string A PHP variable
*/
function twig_raw_filter($string)
{
return $string;
}

View File

@ -1,35 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extension_Optimizer extends Twig_Extension
{
protected $optimizers;
public function __construct($optimizers = -1)
{
$this->optimizers = $optimizers;
}
/**
* {@inheritdoc}
*/
public function getNodeVisitors()
{
return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'optimizer';
}
}

View File

@ -1,112 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extension_Sandbox extends Twig_Extension
{
protected $sandboxedGlobally;
protected $sandboxed;
protected $policy;
public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
{
$this->policy = $policy;
$this->sandboxedGlobally = $sandboxed;
}
/**
* Returns the token parser instances to add to the existing list.
*
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
*/
public function getTokenParsers()
{
return array(new Twig_TokenParser_Sandbox());
}
/**
* Returns the node visitor instances to add to the existing list.
*
* @return array An array of Twig_NodeVisitorInterface instances
*/
public function getNodeVisitors()
{
return array(new Twig_NodeVisitor_Sandbox());
}
public function enableSandbox()
{
$this->sandboxed = true;
}
public function disableSandbox()
{
$this->sandboxed = false;
}
public function isSandboxed()
{
return $this->sandboxedGlobally || $this->sandboxed;
}
public function isSandboxedGlobally()
{
return $this->sandboxedGlobally;
}
public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy)
{
$this->policy = $policy;
}
public function getSecurityPolicy()
{
return $this->policy;
}
public function checkSecurity($tags, $filters, $functions)
{
if ($this->isSandboxed()) {
$this->policy->checkSecurity($tags, $filters, $functions);
}
}
public function checkMethodAllowed($obj, $method)
{
if ($this->isSandboxed()) {
$this->policy->checkMethodAllowed($obj, $method);
}
}
public function checkPropertyAllowed($obj, $method)
{
if ($this->isSandboxed()) {
$this->policy->checkPropertyAllowed($obj, $method);
}
}
public function ensureToStringAllowed($obj)
{
if (is_object($obj)) {
$this->policy->checkMethodAllowed($obj, '__toString');
}
return $obj;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'sandbox';
}
}

View File

@ -1,113 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2012 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Internal class.
*
* This class is used by Twig_Environment as a staging area and must not be used directly.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Extension_Staging extends Twig_Extension
{
protected $functions = array();
protected $filters = array();
protected $visitors = array();
protected $tokenParsers = array();
protected $globals = array();
protected $tests = array();
public function addFunction($name, $function)
{
$this->functions[$name] = $function;
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return $this->functions;
}
public function addFilter($name, $filter)
{
$this->filters[$name] = $filter;
}
/**
* {@inheritdoc}
*/
public function getFilters()
{
return $this->filters;
}
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
{
$this->visitors[] = $visitor;
}
/**
* {@inheritdoc}
*/
public function getNodeVisitors()
{
return $this->visitors;
}
public function addTokenParser(Twig_TokenParserInterface $parser)
{
$this->tokenParsers[] = $parser;
}
/**
* {@inheritdoc}
*/
public function getTokenParsers()
{
return $this->tokenParsers;
}
public function addGlobal($name, $value)
{
$this->globals[$name] = $value;
}
/**
* {@inheritdoc}
*/
public function getGlobals()
{
return $this->globals;
}
public function addTest($name, $test)
{
$this->tests[$name] = $test;
}
/**
* {@inheritdoc}
*/
public function getTests()
{
return $this->tests;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'staging';
}
}

View File

@ -1,64 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2012 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extension_StringLoader extends Twig_Extension
{
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return array(
new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)),
);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'string_loader';
}
}
/**
* Loads a template from a string.
*
* <pre>
* {{ include(template_from_string("Hello {{ name }}")) }}
* </pre>
*
* @param Twig_Environment $env A Twig_Environment instance
* @param string $template A template as a string
*
* @return Twig_Template A Twig_Template instance
*/
function twig_template_from_string(Twig_Environment $env, $template)
{
$name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false));
$loader = new Twig_Loader_Chain(array(
new Twig_Loader_Array(array($name => $template)),
$current = $env->getLoader(),
));
$env->setLoader($loader);
try {
$template = $env->loadTemplate($name);
} catch (Exception $e) {
$env->setLoader($current);
throw $e;
}
$env->setLoader($current);
return $template;
}

View File

@ -1,83 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Interface implemented by extension classes.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface Twig_ExtensionInterface
{
/**
* Initializes the runtime environment.
*
* This is where you can load some file that contains filter functions for instance.
*
* @param Twig_Environment $environment The current Twig_Environment instance
*/
public function initRuntime(Twig_Environment $environment);
/**
* Returns the token parser instances to add to the existing list.
*
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
*/
public function getTokenParsers();
/**
* Returns the node visitor instances to add to the existing list.
*
* @return array An array of Twig_NodeVisitorInterface instances
*/
public function getNodeVisitors();
/**
* Returns a list of filters to add to the existing list.
*
* @return array An array of filters
*/
public function getFilters();
/**
* Returns a list of tests to add to the existing list.
*
* @return array An array of tests
*/
public function getTests();
/**
* Returns a list of functions to add to the existing list.
*
* @return array An array of functions
*/
public function getFunctions();
/**
* Returns a list of operators to add to the existing list.
*
* @return array An array of operators
*/
public function getOperators();
/**
* Returns a list of global variables to add to the existing list.
*
* @return array An array of global variables
*/
public function getGlobals();
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName();
}

View File

@ -1,45 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extensions_Extension_I18n extends Twig_Extension
{
/**
* Returns the token parser instances to add to the existing list.
*
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
*/
public function getTokenParsers()
{
return array(new Twig_Extensions_TokenParser_Trans());
}
/**
* Returns a list of filters to add to the existing list.
*
* @return array An array of filters
*/
public function getFilters()
{
return array(
new Twig_SimpleFilter('trans', 'gettext'),
);
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'i18n';
}
}

View File

@ -1,102 +0,0 @@
<?php
class Twig_Extensions_Extension_Tinyboard extends Twig_Extension
{
/**
* Returns a list of filters to add to the existing list.
*
* @return array An array of filters
*/
public function getFilters()
{
return array(
new Twig_SimpleFilter('filesize', 'format_bytes'),
new Twig_SimpleFilter('truncate', 'twig_truncate_filter'),
new Twig_SimpleFilter('truncate_body', 'truncate'),
new Twig_SimpleFilter('extension', 'twig_extension_filter'),
new Twig_SimpleFilter('sprintf', 'sprintf'),
new Twig_SimpleFilter('capcode', 'capcode'),
new Twig_SimpleFilter('hasPermission', 'twig_hasPermission_filter'),
new Twig_SimpleFilter('date', 'twig_date_filter'),
new Twig_SimpleFilter('poster_id', 'poster_id'),
new Twig_SimpleFilter('remove_whitespace', 'twig_remove_whitespace_filter'),
new Twig_SimpleFilter('count', 'count'),
new Twig_SimpleFilter('ago', 'ago'),
new Twig_SimpleFilter('until', 'until'),
new Twig_SimpleFilter('push', 'twig_push_filter'),
new Twig_SimpleFilter('bidi_cleanup', 'bidi_cleanup'),
new Twig_SimpleFilter('addslashes', 'addslashes')
);
}
/**
* Returns a list of functions to add to the existing list.
*
* @return array An array of filters
*/
public function getFunctions()
{
return array(
new Twig_SimpleFunction('time', 'time'),
new Twig_SimpleFunction('floor', 'floor'),
new Twig_SimpleFunction('timezone', 'twig_timezone_function'),
new Twig_SimpleFunction('hiddenInputs', 'hiddenInputs'),
new Twig_SimpleFunction('hiddenInputsHash', 'hiddenInputsHash'),
);
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'tinyboard';
}
}
function twig_timezone_function() {
return 'Z';
}
function twig_push_filter($array, $value) {
array_push($array, $value);
return $array;
}
function twig_remove_whitespace_filter($data) {
return preg_replace('/[\t\r\n]/', '', $data);
}
function twig_date_filter($date, $format) {
return gmstrftime($format, $date);
}
function twig_hasPermission_filter($mod, $permission, $board = null) {
return hasPermission($permission, $board, $mod);
}
function twig_extension_filter($value, $case_insensitive = true) {
$ext = mb_substr($value, mb_strrpos($value, '.') + 1);
if($case_insensitive)
$ext = mb_strtolower($ext);
return $ext;
}
function twig_sprintf_filter( $value, $var) {
return sprintf($value, $var);
}
function twig_truncate_filter($value, $length = 30, $preserve = false, $separator = '&hellip;') {
if (mb_strlen($value) > $length) {
if ($preserve) {
if (false !== ($breakpoint = mb_strpos($value, ' ', $length))) {
$length = $breakpoint;
}
}
return mb_substr($value, 0, $length) . $separator;
}
return $value;
}

View File

@ -1,133 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a trans node.
*
* @package twig
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Twig_Extensions_Node_Trans extends Twig_Node
{
public function __construct(Twig_NodeInterface $body, Twig_NodeInterface $plural = null, Twig_Node_Expression $count = null, $lineno, $tag = null)
{
parent::__construct(array('count' => $count, 'body' => $body, 'plural' => $plural), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
list($msg, $vars) = $this->compileString($this->getNode('body'));
if (null !== $this->getNode('plural')) {
list($msg1, $vars1) = $this->compileString($this->getNode('plural'));
$vars = array_merge($vars, $vars1);
}
$function = null === $this->getNode('plural') ? 'gettext' : 'ngettext';
if ($vars) {
$compiler
->write('echo strtr('.$function.'(')
->subcompile($msg)
;
if (null !== $this->getNode('plural')) {
$compiler
->raw(', ')
->subcompile($msg1)
->raw(', abs(')
->subcompile($this->getNode('count'))
->raw(')')
;
}
$compiler->raw('), array(');
foreach ($vars as $var) {
if ('count' === $var->getAttribute('name')) {
$compiler
->string('%count%')
->raw(' => abs(')
->subcompile($this->getNode('count'))
->raw('), ')
;
} else {
$compiler
->string('%'.$var->getAttribute('name').'%')
->raw(' => ')
->subcompile($var)
->raw(', ')
;
}
}
$compiler->raw("));\n");
} else {
$compiler
->write('echo '.$function.'(')
->subcompile($msg)
;
if (null !== $this->getNode('plural')) {
$compiler
->raw(', ')
->subcompile($msg1)
->raw(', abs(')
->subcompile($this->getNode('count'))
->raw(')')
;
}
$compiler->raw(");\n");
}
}
protected function compileString(Twig_NodeInterface $body)
{
if ($body instanceof Twig_Node_Expression_Name || $body instanceof Twig_Node_Expression_Constant || $body instanceof Twig_Node_Expression_TempName) {
return array($body, array());
}
$vars = array();
if (count($body)) {
$msg = '';
foreach ($body as $node) {
if (get_class($node) === 'Twig_Node' && $node->getNode(0) instanceof Twig_Node_SetTemp) {
$node = $node->getNode(1);
}
if ($node instanceof Twig_Node_Print) {
$n = $node->getNode('expr');
while ($n instanceof Twig_Node_Expression_Filter) {
$n = $n->getNode('node');
}
$msg .= sprintf('%%%s%%', $n->getAttribute('name'));
$vars[] = new Twig_Node_Expression_Name($n->getAttribute('name'), $n->getLine());
} else {
$msg .= $node->getAttribute('data');
}
}
} else {
$msg = $body->getAttribute('data');
}
return array(new Twig_Node(array(new Twig_Node_Expression_Constant(trim($msg), $body->getLine()))), $vars);
}
}

View File

@ -1,80 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Extensions_TokenParser_Trans extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$count = null;
$plural = null;
if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) {
$body = $this->parser->getExpressionParser()->parseExpression();
} else {
$stream->expect(Twig_Token::BLOCK_END_TYPE);
$body = $this->parser->subparse(array($this, 'decideForFork'));
if ('plural' === $stream->next()->getValue()) {
$count = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
$plural = $this->parser->subparse(array($this, 'decideForEnd'), true);
}
}
$stream->expect(Twig_Token::BLOCK_END_TYPE);
$this->checkTransString($body, $lineno);
return new Twig_Extensions_Node_Trans($body, $plural, $count, $lineno, $this->getTag());
}
public function decideForFork(Twig_Token $token)
{
return $token->test(array('plural', 'endtrans'));
}
public function decideForEnd(Twig_Token $token)
{
return $token->test('endtrans');
}
/**
* Gets the tag name associated with this token parser.
*
* @param string The tag name
*/
public function getTag()
{
return 'trans';
}
protected function checkTransString(Twig_NodeInterface $body, $lineno)
{
foreach ($body as $i => $node) {
if (
$node instanceof Twig_Node_Text
||
($node instanceof Twig_Node_Print && $node->getNode('expr') instanceof Twig_Node_Expression_Name)
) {
continue;
}
throw new Twig_Error_Syntax(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno);
}
}
}

View File

@ -1,81 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a template filter.
*
* Use Twig_SimpleFilter instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
{
protected $options;
protected $arguments = array();
public function __construct(array $options = array())
{
$this->options = array_merge(array(
'needs_environment' => false,
'needs_context' => false,
'pre_escape' => null,
'preserves_safety' => null,
'callable' => null,
), $options);
}
public function setArguments($arguments)
{
$this->arguments = $arguments;
}
public function getArguments()
{
return $this->arguments;
}
public function needsEnvironment()
{
return $this->options['needs_environment'];
}
public function needsContext()
{
return $this->options['needs_context'];
}
public function getSafe(Twig_Node $filterArgs)
{
if (isset($this->options['is_safe'])) {
return $this->options['is_safe'];
}
if (isset($this->options['is_safe_callback'])) {
return call_user_func($this->options['is_safe_callback'], $filterArgs);
}
}
public function getPreservesSafety()
{
return $this->options['preserves_safety'];
}
public function getPreEscape()
{
return $this->options['pre_escape'];
}
public function getCallable()
{
return $this->options['callable'];
}
}

View File

@ -1,37 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a function template filter.
*
* Use Twig_SimpleFilter instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Filter_Function extends Twig_Filter
{
protected $function;
public function __construct($function, array $options = array())
{
$options['callable'] = $function;
parent::__construct($options);
$this->function = $function;
}
public function compile()
{
return $this->function;
}
}

View File

@ -1,39 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a method template filter.
*
* Use Twig_SimpleFilter instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Filter_Method extends Twig_Filter
{
protected $extension;
protected $method;
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
{
$options['callable'] = array($extension, $method);
parent::__construct($options);
$this->extension = $extension;
$this->method = $method;
}
public function compile()
{
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
}
}

View File

@ -1,39 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2011 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a template filter as a node.
*
* Use Twig_SimpleFilter instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Filter_Node extends Twig_Filter
{
protected $class;
public function __construct($class, array $options = array())
{
parent::__construct($options);
$this->class = $class;
}
public function getClass()
{
return $this->class;
}
public function compile()
{
}
}

View File

@ -1,23 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2012 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a callable template filter.
*
* Use Twig_SimpleFilter instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
interface Twig_FilterCallableInterface
{
public function getCallable();
}

View File

@ -1,42 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a template filter.
*
* Use Twig_SimpleFilter instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
interface Twig_FilterInterface
{
/**
* Compiles a filter.
*
* @return string The PHP code for the filter
*/
public function compile();
public function needsEnvironment();
public function needsContext();
public function getSafe(Twig_Node $filterArgs);
public function getPreservesSafety();
public function getPreEscape();
public function setArguments($arguments);
public function getArguments();
}

View File

@ -1,71 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2010 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a template function.
*
* Use Twig_SimpleFunction instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
{
protected $options;
protected $arguments = array();
public function __construct(array $options = array())
{
$this->options = array_merge(array(
'needs_environment' => false,
'needs_context' => false,
'callable' => null,
), $options);
}
public function setArguments($arguments)
{
$this->arguments = $arguments;
}
public function getArguments()
{
return $this->arguments;
}
public function needsEnvironment()
{
return $this->options['needs_environment'];
}
public function needsContext()
{
return $this->options['needs_context'];
}
public function getSafe(Twig_Node $functionArgs)
{
if (isset($this->options['is_safe'])) {
return $this->options['is_safe'];
}
if (isset($this->options['is_safe_callback'])) {
return call_user_func($this->options['is_safe_callback'], $functionArgs);
}
return array();
}
public function getCallable()
{
return $this->options['callable'];
}
}

View File

@ -1,38 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2010 Arnaud Le Blanc
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a function template function.
*
* Use Twig_SimpleFunction instead.
*
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Function_Function extends Twig_Function
{
protected $function;
public function __construct($function, array $options = array())
{
$options['callable'] = $function;
parent::__construct($options);
$this->function = $function;
}
public function compile()
{
return $this->function;
}
}

View File

@ -1,40 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2010 Arnaud Le Blanc
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a method template function.
*
* Use Twig_SimpleFunction instead.
*
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Function_Method extends Twig_Function
{
protected $extension;
protected $method;
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
{
$options['callable'] = array($extension, $method);
parent::__construct($options);
$this->extension = $extension;
$this->method = $method;
}
public function compile()
{
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
}
}

View File

@ -1,39 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2011 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a template function as a node.
*
* Use Twig_SimpleFunction instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
class Twig_Function_Node extends Twig_Function
{
protected $class;
public function __construct($class, array $options = array())
{
parent::__construct($options);
$this->class = $class;
}
public function getClass()
{
return $this->class;
}
public function compile()
{
}
}

View File

@ -1,23 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) 2012 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a callable template function.
*
* Use Twig_SimpleFunction instead.
*
* @author Fabien Potencier <fabien@symfony.com>
* @deprecated since 1.12 (to be removed in 2.0)
*/
interface Twig_FunctionCallableInterface
{
public function getCallable();
}

Some files were not shown because too many files have changed in this diff Show More