Compare commits

..

46 Commits

Author SHA1 Message Date
e90b9cc9c4 Release new version 1.24.1 2020-10-17 12:53:00 +02:00
ede3d7938d Add language meta info and minor restructuring of code 2020-10-17 11:58:39 +02:00
8df28af021 Use $T for translation instead of verwriting $I directly 2020-10-15 22:28:01 +02:00
c3e316d412 Various minor optimizations 2020-10-15 20:46:04 +02:00
919876480d Merge pull request #81 from cypherbits/remove-request-use
For dangerous and only-POST routes check if it is POST request.
2020-10-15 17:13:48 +02:00
4e6cc8d1ab Merge pull request #86 from DanWin/DanWin-funding
Create FUNDING.yml
2020-10-15 17:12:32 +02:00
3dd5de099e Create FUNDING.yml 2020-10-15 17:12:17 +02:00
c71e17103f Fix chrome flashing white on frame reload 2020-10-15 09:43:06 +02:00
8d84e45c3c Add promise not to use any features 2020-10-15 09:42:29 +02:00
d37fc14483 Updated copyright 2020-10-15 08:26:47 +02:00
815d9f203e Improved CSP rules 2020-10-14 13:38:30 +02:00
cca830d9db Fixed syntax error 2020-09-20 21:50:37 +02:00
de04614155 Merge pull request #77 from cypherbits/work1
Little fixes
2020-09-15 20:59:20 +02:00
025709508b Fix guest room bypass #73 2020-09-15 19:37:45 +02:00
34fce5f7ab Merge pull request #75 from cypherbits/master
Fix link filters, image embeds, and redirects.
2020-09-15 18:57:01 +02:00
b7ff7c9eb7 For dangerous and only-POST routes check if it is POST request. 2020-08-05 19:15:37 +02:00
b1c7242752 Little fixes 2020-08-02 17:54:47 +02:00
51fb54e0aa Oops... 2020-08-01 22:40:42 +02:00
e5e3b478dc Fix link filters, image embeds, and redirects. 2020-08-01 21:14:39 +02:00
463d66e11e Include Turikish translation 2020-08-01 20:48:57 +02:00
ed4908b7c7 Merge pull request #70 from creuzwagen/patch-1
Create lang_tr.php
2020-08-01 20:47:41 +02:00
f8fa78f278 Update lang_tr.php
Fully completed
2020-07-15 17:49:57 +03:00
7109b5bd80 Update lang_tr.php 2020-07-14 01:18:44 +03:00
1abedd1f10 Update lang_tr.php 2020-07-14 00:30:15 +03:00
c9699362a0 Create lang_tr.php 2020-07-13 13:53:52 +00:00
cc6d36e7ce Merge pull request #66 from cypherbits/php-version-check
If encryption is enabled, check the PHP version is at least 7.2
2020-06-11 10:39:14 +02:00
217bd9b08a Merge pull request #67 from whalehub/patch-1
Fix indentation in chat.php
2020-06-11 10:36:37 +02:00
972f1a62c1 Fix indentation in chat.php 2020-05-17 14:14:44 +02:00
9ab4622b67 If encryption is enabled, check the PHP version is at least 7.2 2020-05-11 18:24:25 +02:00
62f335d220 Merge branch 'master' of https://github.com/DanWin/le-chat-php 2020-05-11 18:18:03 +02:00
43a6adfa1c Fix undefined index notice 2020-05-07 21:47:49 +02:00
e137eb81ac Updated readme 2020-05-07 21:06:16 +02:00
035cfa6aa4 Harden all cookies 2020-05-07 20:50:20 +02:00
e9a1d61027 Allow data URI for img and media in CSP 2020-05-07 20:38:17 +02:00
a4d2484e24 Merge pull request #63 from cypherbits/fix-security-header
Fix Content-Security-Policy header.
2020-05-07 20:29:27 +02:00
ac46e658bd Merge pull request #64 from cypherbits/faster-encryption-load
If admin defined keys with the right length, do not compute the keys.
2020-05-07 20:28:35 +02:00
9c5e879d7d Merge pull request #62 from cypherbits/fix-session-xss
Fix XSS in session variables.
2020-05-07 20:28:10 +02:00
b7ff54f8d1 Merge branch 'fix-security-header' 2020-05-03 17:42:29 +02:00
5aeca202ca fix 2020-05-03 17:41:56 +02:00
6189120795 Merge branches 'faster-encryption-load', 'fix-security-header' and 'fix-session-xss' 2020-05-03 17:31:10 +02:00
c2cd0258f1 If admin defined keys with the right length, do not compute the keys. 2020-05-03 15:18:41 +02:00
0f97ddd573 Fix Content-Security-Policy header. 2020-05-03 15:08:30 +02:00
81b8b78df0 Fix XSS in session variables. 2020-05-03 11:13:52 +02:00
0f3a04b4de Merge pull request #61 from cypherbits/safe-cookies
Session cookies security hardening.
2020-05-03 10:33:00 +02:00
581aede13f Session cookies security hardening. 2020-05-02 21:53:19 +02:00
e149c9f97d Fix reflected XSS vulnerability 2020-05-02 19:42:34 +02:00
18 changed files with 581 additions and 138 deletions

5
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,5 @@
# These are supported funding model platforms
github: DanWin
liberapay: DanWin1210
custom: "https://www.paypal.me/danwin1210"

View File

@ -1,5 +1,14 @@
Version 1.24.1 - Oct. 17, 2020
Add Turkish translation
Security hardening
Fixed chrome flashing frames white on reload
Version 1.24 - May. 2, 2020
Allow making file upload member-only
Added required tag to captcha input
Add Chinese translation
Security hardening
Fixed chrome flashing frames white on reload
Version 1.23.7 - Feb. 24, 2019
Support V3 hidden services

9
README
View File

@ -1,7 +1,7 @@
GENERAL INFORMATION:
This is a PHP Chat based on LE CHAT v.1.14. An up-to-date copy of this script can be downloaded at https://github.com/DanWin/le-chat-php
The original perl LE CHAT script by Lucky Eddie can be downloaded at http://4fvfamdpoulu2nms.onion/lechat/ or via a tor2web proxy like https://4fvfamdpoulu2nms.onion.to/lechat/ if you don't have TOR installed.
The original perl LE CHAT script by Lucky Eddie can be downloaded at http://4fvfamdpoulu2nms.onion/lechat/ or via a tor2web proxy like https://4fvfamdpoulu2nms.onion.to/lechat/ if you don't have Tor installed.
If you add your own cool features or have a feature request, please tell me and I will add them, if I like them.
Please also let me know about any bugs you find in the code, so I can fix them.
Now a piece of information about the origin of the name "LE CHAT" copied from the original script:
@ -10,7 +10,7 @@ It may even be the French word for "the" if you prefer. Translated from French t
FEATURES:
Optimized for TOR
Optimized for Tor
No JavaScript needed
Cookies supported, but not needed
Captcha
@ -77,6 +77,5 @@ If you never used regex before, check out this starting guide to begin with regu
LIVE DEMO:
If you want to see the script in action, you can visit my TOR hidden service http://tt3j2x4k5ycaa5zt.onion/chat.php or via a tor2web proxy like https://danwin1210.me/chat.php if you don't have TOR installed.
Considering this is a hidden service, you should be prepared for the worst case, as people tend to do illegal activities in the TOR network. I'm not online 24/7 so it might not be possible to remove such content right away.
If you should see illegal content, don't panic. Use the contact form on my site to notify me and clean your browser cache afterwards.
If you want to see the script in action, you can visit my Tor hidden service http://danschat356lctri3zavzh6fbxg2a7lo6z3etgkctzzpspewu7zdsaqd.onion/chat.php or via a tor2web proxy like https://chat.danwin1210.me/chat.php if you don't have Tor installed.
Considering this is a hidden service, you should be prepared for the worst case, as people tend to do illegal activities in the Tor network.

View File

@ -2,7 +2,7 @@ General Information:
--------------------
This is a PHP Chat based on LE CHAT v.1.14. An up-to-date copy of this script can be downloaded at https://github.com/DanWin/le-chat-php
The original perl LE CHAT script by Lucky Eddie can be downloaded at [his site](http://4fvfamdpoulu2nms.onion/lechat/) or via a tor2web proxy like [this one](https://4fvfamdpoulu2nms.onion.to/lechat/) if you don't have TOR installed.
The original perl LE CHAT script by Lucky Eddie can be downloaded at [his site](http://4fvfamdpoulu2nms.onion/lechat/) or via a tor2web proxy like [this one](https://4fvfamdpoulu2nms.onion.to/lechat/) if you don't have Tor installed.
If you add your own cool features or have a feature request, please tell me and I will add them, if I like them.
Please also let me know about any bugs you find in the code, so I can fix them.
Now a piece of information about the origin of the name "LE CHAT" copied from the original script:
@ -12,7 +12,7 @@ It may even be the French word for "the" if you prefer. Translated from French t
Features:
---------
* Optimized for TOR
* Optimized for Tor
* No JavaScript needed
* Cookies supported, but not needed
* Captcha
@ -59,7 +59,7 @@ Translating:
Copy lang_en.php and rename it to lang_YOUR_LANGCODE.php
Then edit the file and translate the messages into your language and change $I to $T at the top.
If you ever use a ' character, you have to escape it by using \' instead or the script will fail.
If you ever use a `'` character, you have to escape it by using `\'` instead or the script will fail.
When you are done, you have to edit the chat script, to include your translation. Simply add a line with
'lang_code' =>'Language name',
to the $L array in the load_lang() function at the bottom, similar to what I did for the German translation.
@ -72,17 +72,16 @@ Regex:
Yes, the chat supports regular expression filtering of messages. As regex tends to be difficult for most people, I decided to give it an extra section here.
Regex is very powerful and can be used to filter messages that contain certain expressions and replace them with something else.
It can be used e.g. to turn BB Code into html, so it is possible to use BB Code in the chat to format messages.
To do this, use this Regex-Match '\[(u|b)\](.*?)\[\/\1\]' and this Regex-Replace '<$1>$2</$1>' and your text will be '[b]bold[/b]' or '[u]underlined[/u]'.
You can also use smilies by using this Regex-Match '(?-i::(cry|eek|lol|sad|smile|surprised|wink):)' and this Regex-Replace '<img src="/pictures/$1.gif" alt=":$1:">'
And now if you enter ':smile:' an image with the smiley will be loaded from your server at '/pictures/smile.gif'.
The following should be escaped by putting '\' in front of it, if you are trying to match one of these characters '/ \ ^ . $ | ( ) [ ] * + ? { } ,'.
I used '/' as delimiter, so you will have to escape that, too. The only options I used is 'i' to make the regex case insensitive.
To do this, use this Regex-Match `\[(u|b)\](.*?)\[\/\1\]` and this Regex-Replace `<$1>$2</$1>` and your text will be `[b]bold[/b]` or `[u]underlined[/u]`.
You can also use smilies by using this Regex-Match `(?-i::(cry|eek|lol|sad|smile|surprised|wink):)` and this Regex-Replace `<img src="/pictures/$1.gif" alt=":$1:">`
And now if you enter `:smile:` an image with the smiley will be loaded from your server at `/pictures/smile.gif`.
The following should be escaped by putting `\` in front of it, if you are trying to match one of these characters `/ \ ^ . $ | ( ) [ ] * + ? { } ,`.
I used `/` as delimiter, so you will have to escape that, too. The only options I used is `i` to make the regex case insensitive.
If you want to test your regex, before applying you can use [this site](http://www.phpliveregex.com/) and enter your Regex and Replacement there and click on preg_replace.
If you never used regex before, check out [this starting guide](http://docs.activestate.com/komodo/4.4/regex-intro.html) to begin with regular expressions.
Live demo:
----------
If you want to see the script in action, you can visit my [TOR hidden service](http://tt3j2x4k5ycaa5zt.onion/chat.php) or via a tor2web proxy like [this one](https://danwin1210.me/chat.php) if you don't have TOR installed.
Considering this is a hidden service, you should be prepared for the worst case, as people tend to do illegal activities in the TOR network. I'm not online 24/7 so it might not be possible to remove such content right away.
If you should see illegal content, don't panic. Use the contact form on my site to notify me and clean your browser cache afterwards. I will remove the content as soon as possible.
If you want to see the script in action, you can visit my [Tor hidden service](http://danschat356lctri3zavzh6fbxg2a7lo6z3etgkctzzpspewu7zdsaqd.onion/chat.php) or via a tor2web proxy like [this one](https://chat.danwin1210.me/chat.php) if you don't have Tor installed.
Considering this is a hidden service, you should be prepared for the worst case, as people tend to do illegal activities in the Tor network.

276
chat.php
View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Main program
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -32,19 +32,20 @@
* 9 - Private messages
*/
send_headers();
// initialize and load variables/configuration
load_config();
$I=[];// Translations
$L=[];// Languages
$U=[];// This user data
$db;// Database connection
$memcached;// Memcached connection
$language;// user selected language
load_config();
$db = null;// Database connection
$memcached = null;// Memcached connection
$language = LANG;// user selected language
$styles = []; //css styles
// set session variable to cookie if cookies are enabled
if(!isset($_REQUEST['session']) && isset($_COOKIE[COOKIENAME])){
$_REQUEST['session']=$_COOKIE[COOKIENAME];
}
$_REQUEST['session'] = preg_replace('/[^0-9a-zA-Z]/', '', $_REQUEST['session'] ?? '');
load_lang();
check_db();
cron();
@ -77,7 +78,7 @@ function route(){
send_post(validate_input());
}
send_post();
}elseif($_REQUEST['action']==='login'){
}elseif($_REQUEST['action']==='login' && isPOST()){
check_login();
send_frameset();
}elseif($_REQUEST['action']==='controls'){
@ -86,7 +87,7 @@ function route(){
}elseif($_REQUEST['action']==='greeting'){
check_session();
send_greeting();
}elseif($_REQUEST['action']==='delete'){
}elseif($_REQUEST['action']==='delete' && isPOST()){
check_session();
if($_REQUEST['what']==='all'){
if(isset($_REQUEST['confirm'])){
@ -98,7 +99,7 @@ function route(){
del_last_message();
}
send_post();
}elseif($_REQUEST['action']==='profile'){
}elseif($_REQUEST['action']==='profile' && isPOST()){
check_session();
$arg='';
if(!isset($_REQUEST['do'])){
@ -112,13 +113,13 @@ function route(){
}
}
send_profile($arg);
}elseif($_REQUEST['action']==='logout'){
}elseif($_REQUEST['action']==='logout' && isPOST()){
kill_session();
send_logout();
}elseif($_REQUEST['action']==='colours'){
check_session();
send_colours();
}elseif($_REQUEST['action']==='notes'){
}elseif($_REQUEST['action']==='notes' && isPOST()){
check_session();
if(isset($_REQUEST['do']) && $_REQUEST['do']==='admin' && $U['status']>6){
send_notes(0);
@ -132,7 +133,7 @@ function route(){
}elseif($_REQUEST['action']==='help'){
check_session();
send_help();
}elseif($_REQUEST['action']==='inbox'){
}elseif($_REQUEST['action']==='inbox' && isPOST()){
check_session();
if(isset($_REQUEST['do'])){
clean_inbox_selected();
@ -140,10 +141,10 @@ function route(){
send_inbox();
}elseif($_REQUEST['action']==='download'){
send_download();
}elseif($_REQUEST['action']==='admin'){
}elseif($_REQUEST['action']==='admin' && isPOST()){
check_session();
send_admin(route_admin());
}elseif($_REQUEST['action']==='setup'){
}elseif($_REQUEST['action']==='setup' && isPOST()){
route_setup();
}else{
send_login();
@ -186,7 +187,7 @@ function route_admin(){
if(isset($_REQUEST['kick']) && isset($_REQUEST['nick'])){
kick_chatter([$_REQUEST['nick']], '', false);
}elseif(isset($_REQUEST['logout']) && isset($_REQUEST['nick'])){
logout_chatter([$_REQUEST['nick']], '', false);
logout_chatter([$_REQUEST['nick']]);
}
send_sessions();
}elseif($_REQUEST['do']==='register'){
@ -248,35 +249,33 @@ function route_setup(){
}
// html output subs
function print_stylesheet($init=false){
global $U;
//default css
echo '<style type="text/css">';
echo 'body{background-color:#000000;color:#FFFFFF;font-size:14px;text-align:center;} ';
echo 'a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} #messages{word-wrap:break-word;} ';
echo 'input,select,textarea{color:#FFFFFF;background-color:#000000;} .messages a img{width:15%} .messages a:hover img{width:35%} ';
echo '.error{color:#FF0033;text-align:left;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;} ';
echo '.setup table table,.admin table table,.profile table table{width:100%;text-align:left} ';
echo '.alogin table,.init table,.destroy_chat table,.delete_account table,.sessions table,.filter table,.linkfilter table,.notes table,.approve_waiting table,.del_confirm table,.profile table,.admin table,.backup table,.setup table{margin-left:auto;margin-right:auto;} ';
echo '.setup table table table,.admin table table table,.profile table table table{border-spacing:0px;margin-left:auto;margin-right:unset;width:unset;} ';
echo '.setup table table td,.backup #restoresubmit,.backup #backupsubmit,.admin table table td,.profile table table td,.login td+td,.alogin td+td{text-align:right;} ';
echo '.init td,.backup #restorecheck td,.admin #clean td,.admin #regnew td,.session td,.messages,.inbox,.approve_waiting td,.choose_messages,.greeting,.help,.login td,.alogin td{text-align:left;} ';
echo '.messages #chatters{max-height:100px;overflow-y:auto;} .messages #chatters a{text-decoration-line:none;} .messages #chatters table{border-spacing:0px;} ';
echo '.messages #chatters th,.messages #chatters td,.post #firstline{vertical-align:top;} ';
echo '.approve_waiting #action td:only-child,.help #backcredit,.login td:only-child,.alogin td:only-child,.init td:only-child{text-align:center;} .sessions td,.sessions th,.approve_waiting td,.approve_waiting th{padding: 5px;} ';
echo '.sessions td td{padding: 1px;} .messages #bottom_link{position:fixed;top:0.5em;right:0.5em;} .messages #top_link{position:fixed;bottom:0.5em;right:0.5em;} ';
echo '.post table,.controls table,.login table{border-spacing:0px;margin-left:auto;margin-right:auto;} .login table{border:2px solid;} .controls{overflow-y:none;} ';
echo '#manualrefresh{display:block;position:fixed;text-align:center;left:25%;width:50%;top:-200%;animation:timeout_messages ';
function prepare_stylesheets($init = false){
global $U, $db, $styles;
$styles['fatal_error'] = 'body{background-color:#000000;color:#FF0033}';
$styles['default'] = 'body,frame{background-color:#000000;color:#FFFFFF;font-size:14px;text-align:center} ';
$styles['default'] .= 'a:visited{color:#B33CB4} a:active{color:#FF0033} a:link{color:#0000FF} #messages{word-wrap:break-word} ';
$styles['default'] .= 'input,select,textarea{color:#FFFFFF;background-color:#000000} .messages a img{width:15%} .messages a:hover img{width:35%} ';
$styles['default'] .= '.error{color:#FF0033;text-align:left} .delbutton{background-color:#660000} .backbutton{background-color:#004400} #exitbutton{background-color:#AA0000} ';
$styles['default'] .= '.setup table table,.admin table table,.profile table table{width:100%;text-align:left} ';
$styles['default'] .= '.alogin table,.init table,.destroy_chat table,.delete_account table,.sessions table,.filter table,.linkfilter table,.notes table,.approve_waiting table,.del_confirm table,.profile table,.admin table,.backup table,.setup table{margin-left:auto;margin-right:auto} ';
$styles['default'] .= '.setup table table table,.admin table table table,.profile table table table{border-spacing:0px;margin-left:auto;margin-right:unset;width:unset} ';
$styles['default'] .= '.setup table table td,.backup #restoresubmit,.backup #backupsubmit,.admin table table td,.profile table table td,.login td+td,.alogin td+td{text-align:right} ';
$styles['default'] .= '.init td,.backup #restorecheck td,.admin #clean td,.admin #regnew td,.session td,.messages,.inbox,.approve_waiting td,.choose_messages,.greeting,.help,.login td,.alogin td{text-align:left} ';
$styles['default'] .= '.messages #chatters{max-height:100px;overflow-y:auto} .messages #chatters a{text-decoration-line:none} .messages #chatters table{border-spacing:0px} ';
$styles['default'] .= '.messages #chatters th,.messages #chatters td,.post #firstline{vertical-align:top} ';
$styles['default'] .= '.approve_waiting #action td:only-child,.help #backcredit,.login td:only-child,.alogin td:only-child,.init td:only-child{text-align:center} .sessions td,.sessions th,.approve_waiting td,.approve_waiting th{padding: 5px} ';
$styles['default'] .= '.sessions td td{padding: 1px} .messages #bottom_link{position:fixed;top:0.5em;right:0.5em} .messages #top_link{position:fixed;bottom:0.5em;right:0.5em} ';
$styles['default'] .= '.post table,.controls table,.login table{border-spacing:0px;margin-left:auto;margin-right:auto} .login table{border:2px solid} .controls{overflow-y:none} ';
$styles['default'] .= '#manualrefresh{display:block;position:fixed;text-align:center;left:25%;width:50%;top:-200%;animation:timeout_messages ';
if(isset($U['refresh'])){
echo $U['refresh']+20;
$styles['default'] .= $U['refresh']+20;
}else{
echo '160';
$styles['default'] .='160';
}
echo 's forwards;z-index:2;background-color:#500000;border:2px solid #ff0000;} ';
echo '@keyframes timeout_messages{0%{top:-200%;} 99%{top:-200%;} 100%{top:0%;}} ';
echo '.notes textarea{height:80vh;width:80%;}';
echo '</style>';
if($init){
$styles['default'] .= 's forwards;z-index:2;background-color:#500000;border:2px solid #ff0000} ';
$styles['default'] .= '@keyframes timeout_messages{0%{top:-200%} 99%{top:-200%} 100%{top:0%}} ';
$styles['default'] .= '.notes textarea{height:80vh;width:80%}';
if($init || ! $db instanceof PDO){
return;
}
$css=get_setting('css');
@ -286,8 +285,18 @@ function print_stylesheet($init=false){
}else{
$colbg=get_setting('colbg');
}
$styles['custom'] = preg_replace("/(\r?\n|\r\n?)/u", '', "body,frame{background-color:#$colbg;color:#$coltxt} $css");
}
function print_stylesheet($init = false){
global $styles;
//default css
echo "<style type=\"text/css\">$styles[default]</style>";
if($init){
return;
}
//overwrite with custom css
echo "<style type=\"text/css\">body{background-color:#$colbg;color:#$coltxt;} $css</style>";
echo "<style type=\"text/css\">$styles[custom]</style>";
}
function print_end(){
@ -296,11 +305,11 @@ function print_end(){
}
function credit(){
return '<small><br><br><a target="_blank" href="https://github.com/DanWin/le-chat-php">LE CHAT-PHP - ' . VERSION . '</a></small>';
return '<small><br><br><a target="_blank" href="https://github.com/DanWin/le-chat-php" rel="noopener">LE CHAT-PHP - ' . VERSION . '</a></small>';
}
function meta_html(){
return '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="Pragma" content="no-cache"><meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate, max-age=0"><meta http-equiv="expires" content="0"><meta name="referrer" content="no-referrer">';
return '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="referrer" content="no-referrer">';
}
function form($action, $do=''){
@ -340,17 +349,16 @@ function thr(){
}
function print_start($class='', $ref=0, $url=''){
global $I;
global $I, $language;
prepare_stylesheets($class === 'init');
send_headers();
if(!empty($url)){
$url=str_replace('&amp;', '&', $url);// Don't escape "&" in URLs here, it breaks some (older) browsers and js refresh!
header("Refresh: $ref; URL=$url");
}
echo '<!DOCTYPE html><html><head>'.meta_html();
echo '<!DOCTYPE html><html lang="'.$language.'"><head>'.meta_html();
if(!empty($url)){
echo "<meta http-equiv=\"Refresh\" content=\"$ref; URL=$url\">";
$ref+=5;//only use js if browser refresh stopped working
$ref*=1000;//js uses milliseconds
echo "<script type=\"text/javascript\">setTimeout(function(){window.location.replace(\"$url\");}, $ref);</script>";
}
if($class==='init'){
echo "<title>$I[init]</title>";
@ -368,7 +376,7 @@ function print_start($class='', $ref=0, $url=''){
function send_redirect($url){
global $I;
$url=htmlspecialchars_decode(rawurldecode($url));
$url=trim(htmlspecialchars_decode(rawurldecode($url)));
preg_match('~^(.*)://~u', $url, $match);
$url=preg_replace('~^(.*)://~u', '', $url);
$escaped=htmlspecialchars($url);
@ -380,7 +388,11 @@ function send_redirect($url){
if(!isset($match[0])){
$match[0]='';
}
echo "<p>$I[nonhttp] <a href=\"$match[0]$escaped\">$match[0]$escaped</a>.</p>";
if(preg_match('~^(javascript|blob|data):~', $url)){
echo "<p>$I[dangerousnonhttp] $match[0]$escaped</p>";
} else {
echo "<p>$I[nonhttp] <a href=\"$match[0]$escaped\">$match[0]$escaped</a>.</p>";
}
echo "<p>$I[httpredir] <a href=\"http://$escaped\">http://$escaped</a>.</p>";
}
print_end();
@ -388,7 +400,7 @@ function send_redirect($url){
function send_access_denied(){
global $I, $U;
header('HTTP/1.1 403 Forbidden');
http_response_code(403);
print_start('access_denied');
echo "<h1>$I[accessdenied]</h1>".sprintf($I['loggedinas'], style_this(htmlspecialchars($U['nickname']), $U['style'])).'<br>';
echo form('logout');
@ -768,7 +780,7 @@ function restore_backup($C){
$note['type']=1;
}
if(MSGENCRYPTED){
$note['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($note['text'], '', AES_IV, ENCRYPTKEY));
$note['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($note['text'], '', AES_IV, ENCRYPTKEY));
}
$stmt->execute([$note['type'], $note['lastedited'], $note['editedby'], $note['text']]);
}
@ -804,7 +816,7 @@ function send_backup($C){
$result=$db->query('SELECT * FROM ' . PREFIX . "notes;");
while($note=$result->fetch(PDO::FETCH_ASSOC)){
if(MSGENCRYPTED){
$note['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
$note['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
}
$code['notes'][]=$note;
}
@ -1387,7 +1399,9 @@ function send_linkfilter($arg=''){
function send_frameset(){
global $I, $U, $db, $language;
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"><html><head>'.meta_html();
prepare_stylesheets();
send_headers();
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"><html lang="'.$language.'"><head>'.meta_html();
echo '<title>'.get_setting('chatname').'</title>';
print_stylesheet();
echo '</head>';
@ -1539,7 +1553,7 @@ function send_notes($type){
}
if(isset($_REQUEST['text'])){
if(MSGENCRYPTED){
$_REQUEST['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($_REQUEST['text'], '', AES_IV, ENCRYPTKEY));
$_REQUEST['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($_REQUEST['text'], '', AES_IV, ENCRYPTKEY));
}
$time=time();
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES (?, ?, ?, ?);');
@ -1573,7 +1587,7 @@ function send_notes($type){
$note['text']='';
}
if(MSGENCRYPTED){
$note['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
$note['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
}
echo "</p>".form('notes');
echo "$hiddendo<textarea name=\"text\">".htmlspecialchars($note['text']).'</textarea><br>';
@ -1855,7 +1869,7 @@ function send_profile($arg=''){
}
echo "<tr><td><table id=\"ignore\"><tr><th>$I[ignore]</th><td>";
echo "<select name=\"ignore\" size=\"1\"><option value=\"\">$I[choose]</option>";
$stmt=$db->prepare('SELECT poster, style FROM ' . PREFIX . 'messages INNER JOIN (SELECT nickname, style FROM ' . PREFIX . 'sessions UNION SELECT nickname, style FROM ' . PREFIX . 'members) AS t ON (' . PREFIX . 'messages.poster=t.nickname) WHERE poster!=? AND poster NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) GROUP BY poster ORDER BY LOWER(poster);');
$stmt=$db->prepare('SELECT poster, style FROM ' . PREFIX . 'messages INNER JOIN (SELECT nickname, style FROM ' . PREFIX . 'sessions UNION SELECT nickname, style FROM ' . PREFIX . 'members) AS t ON (' . PREFIX . 'messages.poster=t.nickname) WHERE poster!=? AND poster NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) GROUP BY poster ORDER BY LOWER(poster);');
$stmt->execute([$U['nickname'], $U['nickname']]);
while($nick=$stmt->fetch(PDO::FETCH_NUM)){
echo '<option value="'.htmlspecialchars($nick[0])."\" style=\"$nick[1]\">".htmlspecialchars($nick[0]).'</option>';
@ -2017,16 +2031,17 @@ function send_download(){
$stmt=$db->prepare('SELECT filename, type, data FROM ' . PREFIX . 'files WHERE hash=?;');
$stmt->execute([$_REQUEST['id']]);
if($data=$stmt->fetch(PDO::FETCH_ASSOC)){
send_headers();
header("Content-Type: $data[type]");
header("Content-Disposition: filename=\"$data[filename]\"");
header('Pragma: no-cache');
header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0, private');
header('Expires: 0');
header("Content-Security-Policy: default-src 'none'");
echo base64_decode($data['data']);
}else{
http_response_code(404);
send_error($I['filenotfound']);
}
}else{
http_response_code(404);
send_error($I['filenotfound']);
}
}
@ -2125,10 +2140,12 @@ function send_error($err){
}
function send_fatal_error($err){
global $I;
echo '<!DOCTYPE html><html><head>'.meta_html();
global $I, $language, $styles;
prepare_stylesheets();
send_headers();
echo '<!DOCTYPE html><html lang="'.$language.'"><head>'.meta_html();
echo "<title>$I[fatalerror]</title>";
echo "<style type=\"text/css\">body{background-color:#000000;color:#FF0033;}</style>";
echo "<style type=\"text/css\">$styles[fatal_error]</style>";
echo '</head><body>';
echo "<h2>$I[fatalerror]: $err</h2>";
print_end();
@ -2207,8 +2224,8 @@ function create_session($setup, $nickname, $password){
}
if($ga===0){
send_error($I['noguests']);
}elseif($ga===3){
$U['entry']=0;
}elseif(in_array($ga, [2, 3], true)){
$U['entry'] = 0;
}
if(get_setting('englobalpass')!=0 && isset($_REQUEST['globalpass']) && $_REQUEST['globalpass']!=get_setting('globalpass')){
send_error($I['wrongglobalpass']);
@ -2224,6 +2241,7 @@ function check_captcha($challenge, $captcha_code){
if(empty($challenge)){
send_error($I['wrongcaptcha']);
}
$code = '';
if(MEMCACHED){
if(!$code=$memcached->get(DBNAME . '-' . PREFIX . "captcha-$_REQUEST[challenge]")){
send_error($I['captchaexpire']);
@ -2248,6 +2266,27 @@ function check_captcha($challenge, $captcha_code){
}
}
function is_definitely_ssl() {
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
return true;
}
if (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
return true;
}
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ('https' === $_SERVER['HTTP_X_FORWARDED_PROTO'])) {
return true;
}
return false;
}
function set_secure_cookie($name, $value){
if (version_compare(PHP_VERSION, '7.3.0') >= 0) {
setcookie($name, $value, ['expires' => 0, 'path' => '/', 'domain' => '', 'secure' => is_definitely_ssl(), 'httponly' => true, 'samesite' => 'Strict']);
}else{
setcookie($name, $value, 0, '/', '', is_definitely_ssl(), true);
}
}
function write_new_session($password){
global $I, $U, $db;
$stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE nickname=?;');
@ -2257,7 +2296,7 @@ function write_new_session($password){
if(password_verify($password, $temp['passhash'])){
$U=$temp;
check_kicked();
setcookie(COOKIENAME, $U['session']);
set_secure_cookie(COOKIENAME, $U['session']);
}else{
send_error("$I[userloggedin]<br>$I[wrongpass]");
}
@ -2284,7 +2323,7 @@ function write_new_session($password){
}
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'sessions (session, nickname, status, refresh, style, lastpost, passhash, useragent, bgcolour, entry, timestamps, embed, incognito, ip, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
$stmt->execute([$U['session'], $U['nickname'], $U['status'], $U['refresh'], $U['style'], $U['lastpost'], $U['passhash'], $useragent, $U['bgcolour'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito'], $ip, $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['nocache_old']]);
setcookie(COOKIENAME, $U['session']);
set_secure_cookie(COOKIENAME, $U['session']);
if($U['status']>=3 && !$U['incognito']){
add_system_message(sprintf(get_setting('msgenter'), style_this(htmlspecialchars($U['nickname']), $U['style'])));
}
@ -2321,7 +2360,7 @@ function approve_session(){
}
function check_login(){
global $I, $U, $db;
global $I, $U;
$ga=(int) get_setting('guestaccess');
if(isset($_REQUEST['session'])){
parse_sessions();
@ -2352,9 +2391,7 @@ function check_login(){
}
}
if($U['status']==1){
if($ga===2 || $ga===3){
$stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=0 WHERE session=?;');
$stmt->execute([$U['session']]);
if(in_array($ga, [2, 3], true)){
send_waiting_room();
}
}
@ -2887,7 +2924,6 @@ function validate_input(){
//ignored
return;
}
$tmp=false;
$stmt=$db->prepare('SELECT s.style, 0 AS inbox FROM ' . PREFIX . 'sessions AS s LEFT JOIN ' . PREFIX . 'members AS m ON (m.nickname=s.nickname) WHERE s.nickname=? AND (s.incognito=0 OR (m.eninbox!=0 AND m.eninbox<=?));');
$stmt->execute([$_REQUEST['sendto'], $U['status']]);
if(!$tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
@ -2932,13 +2968,13 @@ function validate_input(){
'text' =>"<span class=\"usermsg\">$displaysend".style_this($message, $U['style']).'</span>'
];
if(MSGENCRYPTED){
$newmessage['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($newmessage['text'], '', AES_IV, ENCRYPTKEY));
$newmessage['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($newmessage['text'], '', AES_IV, ENCRYPTKEY));
}
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?)');
$stmt->execute([$newmessage['postdate'], $id[0], $newmessage['poster'], $newmessage['recipient'], $newmessage['text']]);
}
if(isset($hash) && $id){
if(!empty($_FILES['file']['type']) && preg_match('~^[a-z0-9/\-\.\+]*$~i', $_FILES['file']['type'])){
if(!empty($_FILES['file']['type']) && preg_match('~^[a-z0-9/\-.+]*$~i', $_FILES['file']['type'])){
$type=$_FILES['file']['type'];
}else{
$type='application/octet-stream';
@ -2978,17 +3014,17 @@ function apply_filter($message, $poststatus, $nickname){
function apply_linkfilter($message){
$filters=get_linkfilters();
foreach($filters as $filter){
$message=preg_replace_callback("/<a href=\"([^\"]+)\" target=\"_blank\">(.*?(?=<\/a>))<\/a>/iu",
$message=preg_replace_callback("/<a href=\"([^\"]+)\" target=\"_blank\" rel=\"noreferrer noopener\">(.*?(?=<\/a>))<\/a>/iu",
function ($matched) use(&$filter){
return "<a href=\"$matched[1]\" target=\"_blank\">".preg_replace("/$filter[match]/iu", $filter['replace'], $matched[2]).'</a>';
return "<a href=\"$matched[1]\" target=\"_blank\" rel=\"noreferrer noopener\">".preg_replace("/$filter[match]/iu", $filter['replace'], $matched[2]).'</a>';
}
, $message);
}
$redirect=get_setting('redirect');
if(get_setting('imgembed')){
$message=preg_replace_callback('/\[img\]\s?<a href="([^"]+)" target="_blank">(.*?(?=<\/a>))<\/a>/iu',
$message=preg_replace_callback('/\[img]\s?<a href="([^"]+)" target="_blank" rel="noreferrer noopener">(.*?(?=<\/a>))<\/a>/iu',
function ($matched){
return str_ireplace('[/img]', '', "<br><a href=\"$matched[1]\" target=\"_blank\"><img src=\"$matched[1]\"></a><br>");
return str_ireplace('[/img]', '', "<br><a href=\"$matched[1]\" target=\"_blank\" rel=\"noreferrer noopener\"><img src=\"$matched[1]\"></a><br>");
}
, $message);
}
@ -2996,17 +3032,17 @@ function apply_linkfilter($message){
$redirect="$_SERVER[SCRIPT_NAME]?action=redirect&amp;url=";
}
if(get_setting('forceredirect')){
$message=preg_replace_callback('/<a href="([^"]+)" target="_blank">(.*?(?=<\/a>))<\/a>/u',
$message=preg_replace_callback('/<a href="([^"]+)" target="_blank" rel="noreferrer noopener">(.*?(?=<\/a>))<\/a>/u',
function ($matched) use($redirect){
return "<a href=\"$redirect".rawurlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";
return "<a href=\"$redirect".rawurlencode($matched[1])."\" target=\"_blank\" rel=\"noreferrer noopener\">$matched[2]</a>";
}
, $message);
}elseif(preg_match_all('/<a href="([^"]+)" target="_blank">(.*?(?=<\/a>))<\/a>/u', $message, $matches)){
}elseif(preg_match_all('/<a href="([^"]+)" target="_blank" rel="noreferrer noopener">(.*?(?=<\/a>))<\/a>/u', $message, $matches)){
foreach($matches[1] as $match){
if(!preg_match('~^http(s)?://~u', $match)){
$message=preg_replace_callback('/<a href="('.preg_quote($match, '/').')\" target=\"_blank\">(.*?(?=<\/a>))<\/a>/u',
$message=preg_replace_callback('/<a href="('.preg_quote($match, '/').')\" target=\"_blank\" rel=\"noreferrer noopener\">(.*?(?=<\/a>))<\/a>/u',
function ($matched) use($redirect){
return "<a href=\"$redirect".rawurlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";
return "<a href=\"$redirect".rawurlencode($matched[1])."\" target=\"_blank\" rel=\"noreferrer noopener\">$matched[2]</a>";
}
, $message);
}
@ -3025,7 +3061,7 @@ function create_hotlinks($message){
$message=preg_replace('~([^\s<>]*:[^\s<>]*@[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d+)?)(?![^<>]*>)~iu', "<<$1>>", $message); // au:th@server given
// 3. likely servers without any hints but not filenames like *.rar zip exe etc.
$message=preg_replace('~((?:[a-z0-9\-]+\.)*(?:[a-z2-7]{55}d|[a-z2-7]{16})\.onion)(?![^<>]*>)~iu', "<<$1>>", $message);// *.onion
$message=preg_replace('~([a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?:\.(?!rar|zip|exe|gz|7z|bat|doc)[a-z]{2,}))(?=[^a-z0-9\-\.]|$)(?![^<>]*>)~iu', "<<$1>>", $message);// xxx.yyy.zzz
$message=preg_replace('~([a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?:\.(?!rar|zip|exe|gz|7z|bat|doc)[a-z]{2,}))(?=[^a-z0-9\-.]|$)(?![^<>]*>)~iu', "<<$1>>", $message);// xxx.yyy.zzz
// Convert every <<....>> into proper links:
$message=preg_replace_callback('/<<([^<>]+)>>/u',
function ($matches){
@ -3040,7 +3076,7 @@ function create_hotlinks($message){
}
function apply_mention($message){
return preg_replace_callback('/\@([^\s]+)/iu', function ($matched){
return preg_replace_callback('/@([^\s]+)/iu', function ($matched){
global $db;
$nick=htmlspecialchars_decode($matched[1]);
$rest='';
@ -3120,7 +3156,7 @@ function add_system_message($mes){
function write_message($message){
global $db;
if(MSGENCRYPTED){
$message['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
$message['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
}
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'messages (postdate, poststatus, poster, recipient, text, delstatus) VALUES (?, ?, ?, ?, ?, ?);');
$stmt->execute([$message['postdate'], $message['poststatus'], $message['poster'], $message['recipient'], $message['text'], $message['delstatus']]);
@ -3241,7 +3277,7 @@ function print_messages($delstatus=0){
function prepare_message_print(&$message, $removeEmbed){
if(MSGENCRYPTED){
$message['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
$message['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
}
if($removeEmbed){
$message['text']=preg_replace_callback('/<img src="([^"]+)"><\/a>/u',
@ -3255,16 +3291,22 @@ function prepare_message_print(&$message, $removeEmbed){
// this and that
function send_headers(){
global $styles;
header('Content-Type: text/html; charset=UTF-8');
header('Pragma: no-cache');
header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0, private');
header('Expires: 0');
header('Referrer-Policy: no-referrer');
header('Content-Security-Policy: referrer never');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: sameorigin');
header('X-XSS-Protection: 1; mode=block');
if($_SERVER['REQUEST_METHOD']==='HEAD'){
header("Permissions-Policy: accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; cross-origin-isolated 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; geolocation 'none'; fullscreen 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; screen-wake-lock 'none'; sync-xhr 'none'; usb 'none'; web-share 'none'; xr-spatial-tracking 'none'; clipboard-read 'none'; clipboard-write 'none'; gamepad 'none'; speaker-selection 'none'; conversion-measurement 'none'; focus-without-user-activation 'none'; hid 'none'; idle-detection 'none'; sync-script 'none'; vertical-scroll 'none'; serial 'none'; trust-token-redemption 'none';");
$style_hashes = '';
foreach($styles as $style) {
$style_hashes .= " 'sha256-".base64_encode(hash('sha256', $style, true))."'";
}
header("Content-Security-Policy: base-uri 'self'; default-src 'none'; font-src 'self'; form-action 'self'; frame-ancestors 'self'; frame-src 'self'; img-src * data:; media-src * data:; style-src 'self' 'unsafe-inline'"); // $style_hashes"); //we can add computed hashes as soon as all inline css is moved to default css
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: sameorigin');
header('X-XSS-Protection: 1; mode=block');
if($_SERVER['REQUEST_METHOD'] === 'HEAD'){
exit; // headers sent, no further processing needed
}
}
@ -3497,7 +3539,7 @@ function destroy_chat($C){
$db->exec('DROP TABLE ' . PREFIX . 'settings;');
if(MEMCACHED){
$memcached->delete(DBNAME . '-' . PREFIX . 'filter');
$memcached->delete(DBANEM . '-' . PREFIX . 'linkfilter');
$memcached->delete(DBNAME . '-' . PREFIX . 'linkfilter');
foreach($C['settings'] as $setting){
$memcached->delete(DBNAME . '-' . PREFIX . "settings-$setting");
}
@ -4009,9 +4051,9 @@ function update_db(){
$stmt=$db->prepare('UPDATE ' . PREFIX . 'messages SET text=? WHERE id=?;');
while($message=$result->fetch(PDO::FETCH_ASSOC)){
if(MSGENCRYPTED){
$message['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
$message['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
}else{
$message['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
$message['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
}
$stmt->execute([$message['text'], $message['id']]);
}
@ -4019,9 +4061,9 @@ function update_db(){
$stmt=$db->prepare('UPDATE ' . PREFIX . 'notes SET text=? WHERE id=?;');
while($message=$result->fetch(PDO::FETCH_ASSOC)){
if(MSGENCRYPTED){
$message['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
$message['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
}else{
$message['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
$message['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
}
$stmt->execute([$message['text'], $message['id']]);
}
@ -4154,19 +4196,20 @@ function load_lang(){
'id' =>'Bahasa Indonesia',
'it' =>'Italiano',
'ru' =>'Русский',
'tr' =>'Türkçe',
'uk' =>'Українська',
'zh_CN' =>'简体中文',
];
if(isset($_REQUEST['lang']) && isset($L[$_REQUEST['lang']])){
$language=$_REQUEST['lang'];
if(!isset($_COOKIE['language']) || $_COOKIE['language']!==$language){
setcookie('language', $language);
set_secure_cookie('language', $language);
}
}elseif(isset($_COOKIE['language']) && isset($L[$_COOKIE['language']])){
$language=$_COOKIE['language'];
}else{
$language=LANG;
setcookie('language', $language);
set_secure_cookie('language', $language);
}
include('lang_en.php'); //always include English
if($language!=='en'){
@ -4178,13 +4221,17 @@ function load_lang(){
}
}
function isPOST(){
return $_SERVER['REQUEST_METHOD'] === 'POST';
}
function load_config(){
mb_internal_encoding('UTF-8');
define('VERSION', '1.24'); // Script version
define('VERSION', '1.24.1'); // Script version
define('DBVERSION', 42); // Database layout version
define('MSGENCRYPTED', false); // Store messages encrypted in the database to prevent other database users from reading them - true/false - visit the setup page after editing!
define('ENCRYPTKEY_PASS', 'MY_SECRET_KEY'); // Encryption key for messages
define('AES_IV_PASS', '1234567890123456'); //AES Encryption IV
define('ENCRYPTKEY_PASS', 'MY_SECRET_KEY'); // Recommended length: 32. Encryption key for messages
define('AES_IV_PASS', '012345678912'); // Recommended length: 12. AES Encryption IV
define('DBHOST', 'localhost'); // Database host
define('DBUSER', 'www-data'); // Database user
define('DBPASS', 'YOUR_DB_PASS'); // Database password
@ -4202,9 +4249,20 @@ function load_config(){
}
define('COOKIENAME', PREFIX . 'chat_session'); // Cookie name storing the session information
define('LANG', 'en'); // Default language
if (MSGENCRYPTED){
//Do not touch: Compute real keys needed by encryption functions
define('ENCRYPTKEY', substr(hash("sha512/256",ENCRYPTKEY_PASS),0, SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES));
define('AES_IV', substr(hash("sha512/256",AES_IV_PASS), 0, SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES));
}
if (MSGENCRYPTED){
if (version_compare(PHP_VERSION, '7.2.0') < 0) {
die("You need at least PHP >= 7.2.x");
}
//Do not touch: Compute real keys needed by encryption functions
if (strlen(ENCRYPTKEY_PASS) !== SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES){
define('ENCRYPTKEY', substr(hash("sha512/256",ENCRYPTKEY_PASS),0, SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES));
}else{
define('ENCRYPTKEY', ENCRYPTKEY_PASS);
}
if (strlen(AES_IV_PASS) !== SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES){
define('AES_IV', substr(hash("sha512/256",AES_IV_PASS), 0, SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES));
}else{
define('AES_IV', AES_IV_PASS);
}
}
}

View File

@ -3,6 +3,6 @@ input, select, textarea, button {padding: 0.2em; border: 1px solid #ffffff; bord
#messages small {color: #989898}
#messages {display: block; width: 79%}
.messages #topic {display: block; width: 79%}
.messages #chatters {display: block; float:right; width: 20%; overflow-y: auto; position:fixed; right:0px; max-height:100%; bottom:2em; top:2em;}
.messages #chatters {display: block; float:right; width: 20%; overflow-y: auto; position:fixed; right:0; max-height:100%; bottom:2em; top:2em;}
.messages #chatters td, #chatters tr, #chatters th {display: table-row; width: 100%!important;}
.messages #chatters table a {display: table-row; line-height: 0;}

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Bulgarian translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Czech translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -19,7 +19,7 @@
*/
//Native language name: čeština
$I=[
$T=[
'nodb' => 'Chyba databáze!',
'nodbsetup' => 'Žádné připojení k databázi, prosím vytvořte databázi a upravte script pro použití správné databáze se zadaným uživatelským jménem a heslem!',
'changelang' => 'Změnit jazyk:',

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - German translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -241,6 +241,7 @@ $T=[
'YellowGreen' => 'Gelbgrün',
'redirectto' => 'Leite weiter zu:',
'nonhttp' => 'Nicht-http Adresse angefordert:',
'dangerousnonhttp' => 'Nicht-http Adresse angefordert. Kopieren Sie diesen Link und fügen ihn ein, falls Sie wirklich sicher sind.:',
'httpredir' => 'Wenn sie nicht funktioniert, probiere diese:',
'actions' => 'Aktionen',
'sesip' => 'IP-Adresse',

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - English translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -241,6 +241,7 @@ $I=[
'YellowGreen' => 'Yellow green',
'redirectto' => 'Redirecting to:',
'nonhttp' => 'Non-http link requested:',
'dangerousnonhttp' => 'Dangerous non-http link requested, copy paste this link if you are really sure:',
'httpredir' => 'If it\'s not working, try this one:',
'actions' => 'Actions',
'sesip' => 'IP-Address',

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Spanish translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - French translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Indonesian translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Italian translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Russian translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

371
lang_tr.php Normal file
View File

@ -0,0 +1,371 @@
<?php
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - English translation
*
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Native language name: Türkçe
$T=[
'nodb' => 'Veritabanına bağlantı yok!',
'nodbsetup' => 'Veritabanına bağlantı yok, lütfen bir veritabanı oluşturun ve doğru veritabanını kullanmak için script\'i verilen kullanıcı adı ve şifre ile düzenleyin!',
'changelang' => 'Dili değiştir:',
'expire' => 'Geçersiz/tarihi geçmiş oturum',
'kicked' => 'Atıldınız!',
'invalnick' => 'Geçersiz kullanıcı adı (En fazla %1$d harf ve normal ifade "%2$s" ile eşleşmeli)',
'invalpass' => 'Geçersiz şifre (En az %1$d harf ve normal ifade "%2$s" ile eşleşmeli)',
'noconfirm' => 'Şifreler birbirleriyle eşleşmiyor!',
'incorregex' => 'Yanlış normal ifade!',
'bottom' => 'Alt',
'top' => 'Üst',
'choose' => '(seç)',
'setup' => 'Sohbet kurulumu',
'init' => 'İlk kurulum',
'sulogin' => 'Superadmin Girişi',
'sunick' => 'Superadmin Kullanıcı adı:',
'supass' => 'Superadmin Şifre:',
'suconfirm' => 'Şifreyi doğrula:',
'susuccess' => 'Başarılı bir şekilde kayıt olundu!',
'initbtn' => 'Sohbeti Başlat',
'initdbexist' => 'Veritabanı tabloları zaten bulunuyor! Devam etmek için, tabloları manuel olarak silmeniz lazım.',
'initsuexist' => 'Bir Superadmin zaten bulunuyor!',
'initgosetup' => 'Kurulum sayfasına git',
'captcha' => 'Captcha',
'enabled' => 'Etkinleştirildi',
'onlyguests' => 'Sadece konuklar için',
'disabled' => 'Devre dışı',
'simple' => 'Basit',
'moderate' => 'Orta',
'extreme' => 'Aşırı',
'nick' => 'Kullanıcı adı:',
'pass' => 'Şifre:',
'globalloginpass' => 'Global şifre:',
'login' => 'Giriş',
'dbupdate' => 'Veritabanı başarıyla güncellendi!',
'sysmessages' => 'Sistem iletileri',
'msgenter' => 'Giriş',
'msgexit' => 'Ayrılınıyor',
'msgmemreg' => 'Üye kaydedildi',
'msgsureg' => 'Başvuru kaydedildi',
'msgkick' => 'Atıldı',
'msgmultikick' => 'Toplu atıldı',
'msgallkick' => 'Hepsi atıldı',
'msgclean' => 'Oda temizlendi',
'dateformat' => '<a target="_blank" href="http://php.net/manual/en/function.date.php#refsect1-function.date-parameters">Tarih biçimlendirme</a>',
'admfunc' => 'Yönetici işlemleri',
'allguests' => 'Tüm konuklar',
'cleanmsgs' => 'İletileri temizle',
'room' => 'Tüm oda',
'selection' => 'Seçim',
'cleannick' => 'Şu kullanıcı adını:',
'clean' => 'Temizle',
'kickchat' => 'Kullanıcıyı at (%d dakika)',
'kickreason' => 'Atılma nedeni:',
'kickpurge' => 'İletileri temizle',
'kick' => 'At',
'logoutinact' => 'İnaktif kişiyi oturumdan çıkar',
'logout' => ıkış yap',
'sessions' => 'Aktif oturumlara bak',
'view' => 'Görüntüle',
'filter' => 'Filtrele',
'guestacc' => 'Konuk erişimini değiştir',
'guestallow' => 'İzin ver',
'guestwait' => 'Bekleme odasına izin ver',
'adminallow' => 'Moderatör onayı gerekiyor',
'guestdisallow' => 'Sadece üyeler',
'addsuguest' => 'Başvuru kayıt et',
'register' => 'Kayıt ol',
'admmembers' => 'Üyeler',
'memdel' => 'Veritabanından sil',
'memdeny' => 'Erişimi reddet (!)',
'memsuguest' => 'Set to applicant (G)',
'memreg' => 'Normal üye yap',
'memmod' => 'Moderatör yap (Ü)',
'memsumod' => 'Süpermod yap (SM)',
'memadm' => 'Yönetici yap (Y)',
'change' => 'Değiştir',
'regguest' => 'Misafir kaydet',
'regmem' => 'Yeni Üye kaydet',
'sessact' => 'Aktif Oturumlar',
'sessnick' => 'Kullanıcı adı',
'sesstimeout' => 'Zaman aşımı',
'sessua' => 'User-Agent',
'fid' => 'ID Filtrele:',
'match' => 'Eşleş',
'replace' => 'Değiştir',
'allowpm' => 'Allow in PM',
'regex' => 'Regex',
'apply' => 'Uygula',
'newfilter' => 'Yeni filtre:',
'add' => 'Ekle',
'noframes' => 'Bu sohbet <b>çerçeveleri</b> kullanıyor. Please enable frames in your browser or use a suitable one!',
'delselmes' => 'Seçili iletileri sil',
'staffnotes' => 'Yetkili notları',
'adminnotes' => 'Yönetici notları',
'notessaved' => 'Notlar kaydedildi!',
'lastedited' => 'Son düzenleme %1$s tarafından %2$s tarihinde',
'savenotes' => 'Notları kaydet',
'waitingroom' => 'Bekleme odası',
'waittext' => 'Hoş geldiniz %1$s, girişiniz geciktirildi, sohbete %2$d saniye içinde erişebilirsiniz.',
'admwaittext' => 'Hoş geldiniz %1$s, girişiniz geciktirildi, sohbete bir moderatör girmenize izin verirse erişebilirsiniz.',
'waitreload' => 'Eğer sayfa %d saniye içinde yenilenmiyorsa, elinizle yenilemek için alttaki düğmeyi kullanın!',
'reload' => 'Yenile',
'rules' => 'Kurallar',
'talkto' => 'Şuna gönder',
'toall' => 'Tüm kullanıcılar',
'tomem' => 'Sadece üyeler',
'tostaff' => 'Sadece yetkililer',
'toadmin' => 'Sadece yönetici',
'alsopurge' => 'Ayrıca iletileri temizle',
'dellast' => 'Son iletiyi sil',
'delall' => 'Tüm iletileri sil',
'switchsingle' => 'Tek-satıra geç',
'switchmulti' => 'Çoklu-satıra geç',
'help' => 'Yardım',
'helpguest' => 'Tüm işlemler anlaşılabilir olmalı, sadece düğmeleri kullanın. Profilinizde yenileme aralığını ve yazı rengini değiştirebilir, aynı zamanda üyeleri göz ardı edebilirsiniz.<br><u>Not:</u> Bu bir sohbet, eğer konuşmayı bırakırsanız, bir süre sonra otomatik olarak oturumdan atılırsınız.',
'helpembed' => 'Eğer iletinize bir görsel eklemek istiyorsanız, basit bir şekilde görsel URL\'sinin önüne [img] koyun. Örnek: [img]http://example.com/images/file.jpg yazmak iletinizdeki görseli ekler.',
'helpmem' => 'Üyeler: Profilinizde biraz daha seçenek var. Yazı tipini ayarlayabilir, şifrenizi istediğiniz zaman değiştirebilir ve tabii ki hesabınızı silebilirsiniz.',
'helpmod' => 'Moderatörler: En alttaki Yönetici düğmesine dikkat edin. Odayı temizleyebileceğiniz, kişileri atabileceğiniz, aktif oturumları görebileceğiniz ve konuk erişimini kapatabileceğiniz bir sayfa gelecektir.',
'helpadm' => 'Yöneticiler: Konukları kaydedebilir, üyeleri düzenleyebilir ve yeni kullanıcı adları kaydedebilirsiniz.',
'profile' => 'Profiliniz',
'ignore' => 'Görmezden gel',
'unignore' => 'Görmezden gelmeyi bırak',
'refreshrate' => 'Yenileme aralığı (5-150 saniye)',
'fontcolour' => 'Yazı tipi rengi',
'viewexample' => 'Örnekleri görüntüle',
'bgcolour' => 'Arkaplan rengi',
'fontface' => 'Yazıtipi yüzü',
'roomdefault' => 'Oda Varsayılanı',
'bold' => 'Kalın',
'italic' => 'İtalik',
'small' => 'Küçük',
'fontexample' => 'Seçtiğin yazı tipi için örnek',
'timestamps' => 'Zaman damgalarını göster',
'embed' => 'Gömülü görseller',
'incognito' => 'Incognito modu',
'changenick' => 'Kullanıcı adını değiştir',
'changepass' => 'Şifreyi değiştir',
'oldpass' => 'Eski şifre:',
'newpass' => 'Yeni şifre:',
'confirmpass' => 'Yeni şifreyi doğrula:',
'savechanges' => 'Değişiklikleri kaydet',
'reloadpb' => 'Posta Kutusunu Yenile',
'reloadmsgs' => 'İletileri yenile',
'chgprofile' => 'Profil',
'adminbtn' => 'Yönetici',
'admnotes' => 'Yönetici Notları',
'notes' => 'Notlar',
'clone' => 'Klonla',
'randh' => 'Kurallar & Yardım',
'exit' => 'Sohbetten çık',
'bye' => 'Görüşürüz %s, en yakın zamanda yine uğra!',
'colourtable' => 'Renk tablosu',
'backtoprofile' => 'Profiline geri dön',
'copy' => 'Kopyala:',
'choosecol' => 'Konuklar, bir renk seçin:',
'randomcol' => 'Rastgele renk',
'enter' => 'Sohbete gir',
'error' => 'Hata',
'members' => 'Üyeler',
'guests' => 'Konuklar',
'approveguests' => '%d tane onaylanacak konuk',
'allowchecked' => 'Kontrol edilenlere izin ver',
'allowall' => 'Hepsine izin ver',
'denychecked' => 'Kontrol edilenleri reddet',
'denyall' => 'Hepsini reddet',
'denymessage' => 'Reddedilene ileti gönder:',
'butallowdeny' => 'Gönder',
'waitempty' => 'Onaylanacak daha fazla giriş isteği yok.',
'wrongcaptcha' => 'Yanlış captcha',
'captchaexpire' => 'Captcha zaten kullanılmış veya zamanıılmış.',
'noguests' => 'Üzgünüm, şu anlık sadece üyeler!',
'curchat' => 'Şu anda odada %d kişi var:',
'cantreg' => '%s kayıt edilemiyor',
'alreadyreged' => '%s zaten kayıtlı.',
'successreg' => '%s kayıt oldu.',
'cantchgstat' => '%s\'ın statüsü değiştirilemiyor!',
'succdel' => '%s başarılı bir şekilde veritabanından silindi.',
'succchg' => '%s\'ın statüsü başarıyla değiştirildi.',
'wrongpass' => 'Yanlış şifre!',
'wrongglobalpass' => 'Yanlış global şifre!',
'succprofile' => 'Profiliniz başarıyla kaydedildi.',
'backtologin' => 'Giriş ekranına geri dön.',
'backtochat' => 'Sohbete geri dön.',
'Beige' => 'Bej',
'Black' => 'Kahverengi',
'Blue' => 'Mavi',
'BlueViolet' => 'Mavi mor',
'Brown' => 'Kahverengi',
'Cyan' => 'Camgöbeği',
'DarkBlue' => 'Koyu mavi',
'DarkGreen' => 'Koyu yeşil',
'DarkRed' => 'Koyu red',
'DarkViolet' => 'Koyu mor',
'DeepSkyBlue' => 'Gökyüzü mavisi',
'Gold' => 'Altın',
'Grey' => 'Gri',
'Green' => 'Yeşil',
'HotPink' => 'Sıcak pembe',
'Indigo' => 'Indigo',
'LightBlue' => 'Açık mavi',
'LightGreen' => 'Açık yeşil',
'LimeGreen' => 'Limon yeşili',
'Magenta' => 'Magenta',
'Olive' => 'Zeytin',
'Orange' => 'Turuncu',
'OrangeRed' => 'Turuncu kırmızı',
'Purple' => 'Mor',
'Red' => 'Kırmızı',
'RoyalBlue' => 'Kraliyet mavisi',
'SeaGreen' => 'Deniz yeşili',
'Sienna' => 'Sienna',
'Silver' => 'Gümüş',
'Tan' => 'Tan',
'Teal' => 'Teal',
'Violet' => 'Mor',
'White' => 'Beyaz',
'Yellow' => 'Sarı',
'YellowGreen' => 'Sarı yeşil',
'redirectto' => 'Şuna yönlendiriliyor:',
'nonhttp' => 'HTTP olmayan bağlantı istenildi:',
'dangerousnonhttp' => 'Tehlikeli HTTP olmayan bağlantı istenildi, eğer eminseniz bu bağlantıyı kopyalayıp yapıştırın:',
'httpredir' => 'Eğer çalışmıyorsa, bunu deneyin:',
'actions' => 'Eylemler',
'sesip' => 'IP Adresi',
'css' => 'CSS Stili',
'memberexpire' => 'Üye zaman aşımı (dakika)',
'guestexpire' => 'Konuk zaman aşımı (dakika)',
'kickpenalty' => 'Atım cezası (dakika)',
'entrywait' => 'Bekleme odası zamanı (saniye)',
'captchatime' => 'Captcha zaman aşımı (saniye)',
'messageexpire' => 'İleti zaman aşımı (dakika)',
'messagelimit' => 'İleti sınırı (herkese açık)',
'maxmessage' => 'Maksimum ileti uzunluğu',
'confirm' => 'Emin misiniz?',
'yes' => 'Evet',
'no' => 'Hayır',
'colbg' => 'Arkaplan rengi',
'coltxt' => 'Yazı rengi',
'maxname' => 'Maksimum şifre uzunluğu',
'minpass' => 'Minimum şifre uzunluğu',
'defaultrefresh' => 'Varsayılan mesaj yenileme süresi (saniye)',
'suguests' => 'Başvuru sahiplerini etkinleştir',
'rulestxt' => 'Kurallar (html)',
'imgembed' => 'Gömülü görseller',
'trackip' => 'Oturum IP\'sini göster',
'captchachars' => 'Captcha\'da kullanılan harfler',
'memkick' => 'Eğer herhangi bir moderatör yoksa, üyeler birini atabilir',
'forceredirect' => 'Yönlendirmeye zorla',
'redirect' => 'Özel yönlendirme script\'i',
'backuprestore' => 'Yedekle ve onar',
'backup' => 'Backup',
'restore' => 'Onar',
'settings' => 'Ayarlar',
'linkfilter' => 'Linkfilter',
'chatname' => 'Sohbet ismi',
'destroy' => 'Sohbeti yok et',
'destroyed' => 'Sohbet başarıyla yok edildi',
'topic' => 'Konu',
'passreset' => 'Şifreyi değiştir',
'cantresetpass' => 'Şifre değiştirilemiyor',
'succpassreset' => 'Şifre başarıyla değiştirildi',
'entermsg' => '%s sohbete katıldı.',
'exitmsg' => '%s sohbetten çıktı.',
'memregmsg' => '%s artık bir kayıtlı üye.',
'suregmsg' => '%s artık başvuru sahibi.',
'kickmsg' => '%s atıldı.',
'multikickmsg' => '%s atıldı.',
'allkickmsg' => 'Tüm konuklar atıldı.',
'cleanmsg' => '%s temizlendi.',
'sendallmsg' => '%s - ',
'sendmemmsg' => '[Ü] %s - ',
'sendmodmsg' => '[Yetkili] %s - ',
'sendadmmsg' => '[Yönetici] %s - ',
'sendprvmsg' => '[%1$s to %2$s] - ',
'msgsendall' => 'Herkese gönder',
'msgsendmem' => 'Sadece üyelere gönder',
'msgsendmod' => 'Sadece yetkililere gönder',
'msgsendadm' => 'Sadece yöneticilere gönder',
'msgsendprv' => 'Özel ileti',
'numnotes' => 'Number of notes revisions to keep',
'revisions' => 'Revisions:',
'older' => 'Daha eski',
'newer' => 'Daha yeni',
'accessdenied' => 'Erişin reddedildi',
'loggedinas' => '%s olarak giriş yaptınız ve bu bölüme erişiminiz yok.',
'newnickname' => 'Yeni kullanıcı adı:',
'nicknametaken' => 'Kullanıcı adı zaten alınmış',
'nopass' => 'Geçersiz şifre (En az %d harf), kullanıcı adı değiştirilmiyor',
'gdextrequired' => 'Bu özellik için PHP\'nin gd uzantısı gerekiyor. Lütfen önce onu kurun.',
'memcachedextrequired' => 'Önbelleğe alma özelliği için PHP\'nin memcached uzantısı gerekiyor. Lütfen ilk önce onu kurun veya memcached özelliğini devre dışı bırakın.',
'sodiumextrequired' => 'Şifreleme için PHP\'nin libsodium uzantısı gerekiyor. Lütfen ilk önce onu kurun veya şifreleme özelliğini devre dışı bırakın.',
'pdo_mysqlextrequired' => 'Seçili veritabanı sürücüsü için PHP\'nin pdo_mysql uzantısı gerekiyor. Lütfen ilk önce onu kurun.',
'pdo_pgsqlextrequired' => 'Seçili veritabanı sürücüsü için PHP\'nin pdo_mysql uzantısı gerekiyor. Lütfen ilk önce onu kurun.',
'pdo_sqliteextrequired' => 'Seçili veritabanı sürücüsü için PHP\'nin pdo_sqlite uzantısı gerekiyor. Lütfen ilk önce onu kurun.',
'jsonextrequired' => 'Bu özellik için PHP\'nin json uzantısı gerekiyor. Lütfen ilk önce onu kurun.',
'sendmail' => 'Yeni herkese açık mesajla posta gönder',
'mailsender' => 'Bu adresi kullanarak posta gönder',
'mailreceiver' => 'Bu adrese posta gönder',
'modfallback' => 'Eğer konukları onaylayacak moderatör yoksa, bekleme odasına düş',
'regpass' => 'Kayıt olmak için<br>şifreyi tekrarla',
'guestreg' => 'Konukların kendilerini kayıt etmelerine izin ver',
'asmember' => 'Üye olarak',
'assuguest' => 'Başvuru sahibi olarak',
'fatalerror' => 'Kritik hata',
'prevmatch' => 'Eşleşmeniz aşağıdaki gibiydi',
'matchtoolong' => 'Eşleşmeniz çok uzundu. En fazla 255 harf kullanabilirsiniz. Bölmeyi deneyin.',
'nocache' => 'Otomatik kaydırma (eski tarayıclar veya yukarıdan-aşağıya görüntüleme için).',
'disablepm' => 'Özel mesajları devre dışı bırak',
'disablechat' => 'Sohbeti devre dışı bırak',
'disabletext' => 'Sohbet mesajı devre dışı bıraktı (html)',
'disabledtext' => 'Geçici olarak devre dışı',
'defaulttz' => 'Varsayılan zaman dilimi',
'tz' => 'Zaman dilimi',
'optional' => '(isteğe bağlı)',
'userloggedin' => 'Bu kullanıcı ismine sahip birisi zaten giriş yapmış.',
'regednick' => 'Bu kullanıcı adı kayıtlı bir üyeye ait.',
'eninbox' => 'Çevrimdışı gelen kutusunu etkinleştir',
'inboxmsgs' => 'Gelen kutunuzdaki %d mesajı okuyun',
'offline' => '(çevrimdışı)',
'deleteacc' => 'Hesabı sil',
'eninnone' => 'Hiç kimse için',
'eninall' => 'Herkes için',
'eninmem' => 'Sadece üyeler için',
'eninstaff' => 'Sadece yetkililer için',
'eninadmin' => 'Sadece yöneticiler için',
'nickregex' => 'Kullanıcı adı regex',
'passregex' => 'Şifre regex',
'externalcss' => 'Dış CSS dosyasının bağlantısı',
'greetingmsg' => 'Hoş geldin %s!',
'entryhelp' => 'Eğer çerçeve %d saniye içinde yenilenmiyorsa, tarayıcınızda otomatik yönlendirmeyi (meta refresh) açmanız lazım. Ayrıca web filtresi, yerel proxy aracı veya tarayıcı uzantılarının otomatik yönlendirmeyi engellemediğinden emin olun! Buna örnek olarak "Polipo", "NoScript", vb. verilebilir<br>Geçici bir çözüm olarak (veya sunucu/proxy yenileme hataları olursa) her zaman aşağıdaki düğmeler ile manuel olarak yenileyebilirsiniz.',
'enablegreeting' => 'İletileri göstermeden önce selamlama mesajı göster',
'unban' => 'Yasaklamayı kaldır',
'sortupdown' => 'İletileri yukarıdan aşağıya doğru sırala',
'sortframe' => 'Yeniden düzenle',
'cs' => 'Büyük harf/küçük harf duyarlı',
'hidechatters' => 'Sohbet edenlerin listesini gizle',
'enfileupload' => 'Dosya yüklemelerine izin ver',
'msgattache' => 'Ek',
'filenotfound' => 'Dosya bulunamadı!',
'maxuploadsize' => 'KB olarak en fazla yükleme boyutu',
'maxsize' => 'En fazla %d KB',
'cssupdate' => 'Not: Default CSS is now hardcoded and can be removed from the CSS setting',
'manualrefresh' => 'Manuel yenileme gerekli',
'personalnotes' => 'Kişisel notlar',
'filtermodkick' => 'Moderatörler için atma filtresini etkinleştir',
];

View File

@ -2,7 +2,7 @@
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - Ukrainian translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -8,7 +8,7 @@ $file = "<?php
/*
* LE CHAT-PHP - a PHP Chat based on LE CHAT - $english translation
*
* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
* Copyright (C) 2015-2020 Daniel Winzen <daniel@danwin1210.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by