From 7e0940d57d22d89c06282f8dbf6fb88a2d46306c Mon Sep 17 00:00:00 2001 From: hide_d Date: Sun, 14 Jan 2018 02:31:25 +0900 Subject: [PATCH] =?UTF-8?q?=3F>=20=EC=A0=9C=EA=B1=B0=20replace=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EB=94=94=EB=B2=84=EA=B9=85=20=EC=9A=A9=EB=8F=84?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 15 + _common.php | 1 - che_close/_119_b.php | 1 - che_close/_admin1_submit.php | 2 - che_close/_admin2_submit.php | 1 - che_close/_admin3_submit.php | 2 - che_close/_admin4_submit.php | 2 - che_close/_admin5_submit.php | 2 - che_close/_simul.php | 2 +- che_close/a_traffic.php | 1 - che_close/a_vote.php | 1 - che_close/analytics.php | 3 +- che_close/c_auction.php | 1 - che_close/c_dipcenter.php | 2 - che_close/c_double.php | 2 - che_close/c_msgsubmit.php | 2 - che_close/c_myBossInfo.php | 2 - che_close/c_nationrule.php | 2 - che_close/c_tournament.php | 1 + che_close/c_troop.php | 2 - che_close/c_vacation.php | 2 - che_close/config.php | 4 +- che_close/d_ally.php | 2 - che_close/d_cancel.php | 2 - che_close/d_cease.php | 2 - che_close/d_merge.php | 2 - che_close/d_scout.php | 3 - che_close/d_setting/_common.php | 1 - che_close/d_surrender.php | 1 - che_close/data/connected.php | 2 +- che_close/event_1.php | 2 - che_close/event_2.php | 2 - che_close/event_3.php | 2 - che_close/event_4.php | 2 - che_close/func.php | 1 - che_close/func_auction.php | 1 - che_close/func_history.php | 1 - che_close/func_http.php | 1 - che_close/func_npc.php | 1 - che_close/func_process.php | 1 - che_close/func_string.php | 1 - che_close/install2_ok.php | 1 - che_close/install3_ok.php | 4 +- che_close/install_ok.php | 5 +- che_close/join_post.php | 2 - che_close/join_post.php.orig | 1 - che_close/join_token.php | 2 - che_close/lib.php | 1 - che_close/login_process.php | 1 - che_close/logout_process.php | 3 +- che_close/phpinfo.php | 3 - d_setting/_common.php | 1 - d_setting/set.php | 2 +- e_lib/license.txt | 1 + e_lib/meekrodb.2.3.class.php | 2 +- e_lib/phpmailer5/class.phpmailer.php | 2 +- e_lib/phpmailer5/class.pop3.php | 2 +- e_lib/phpmailer5/class.smtp.php | 2 +- e_lib/src/utilphp/util.php | 2535 +++++++++++++++++ e_lib/util.php | 10 + e_lib/utilphp-1.1.0/.coveralls.yml | 1 + e_lib/utilphp-1.1.0/.gitignore | 4 + e_lib/utilphp-1.1.0/.travis.yml | 22 + e_lib/utilphp-1.1.0/CHANGELOG.md | 86 + e_lib/utilphp-1.1.0/CONTRIBUTORS.md | 48 + e_lib/utilphp-1.1.0/LICENSE.md | 24 + e_lib/utilphp-1.1.0/README.md | 123 + e_lib/utilphp-1.1.0/composer.json | 24 + e_lib/utilphp-1.1.0/docs/css/docs.css | 168 ++ e_lib/utilphp-1.1.0/docs/favicon.png | Bin 0 -> 803 bytes .../docs/images/awesome_var_dump.jpg | Bin 0 -> 41429 bytes .../utilphp-1.1.0/docs/images/background.png | Bin 0 -> 1028 bytes .../docs/images/utility_logo.png | Bin 0 -> 84870 bytes e_lib/utilphp-1.1.0/docs/index.html | 1234 ++++++++ e_lib/utilphp-1.1.0/phpunit.xml.dist | 25 + e_lib/utilphp-1.1.0/tests/README.md | 39 + e_lib/utilphp-1.1.0/tests/UtilTest.php | 1183 ++++++++ f_config/DB.php | 2 +- f_config/DBS.php | 2 +- f_config/MAIL.php | 2 +- f_config/SESSION.php | 2 +- f_config/SETTING.php | 2 +- f_config/SETTINGS.php | 2 +- f_config/_common.php | 2 +- f_config/app.php | 2 +- f_config/config.php | 2 +- f_func/_common.php | 2 +- f_func/class._Chat.php | 2 +- f_func/class._DB.php | 2 +- f_func/class._JSON.php | 2 +- f_func/class._Lock.php | 2 +- f_func/class._Log.php | 2 +- f_func/class._Mail.php | 2 +- f_func/class._Process.php | 2 +- f_func/class._Queue.php | 2 +- f_func/class._Session.php | 2 +- f_func/class._Setting.php | 2 +- f_func/class._String.php | 1 - f_func/class._Time.php | 2 +- f_func/class._Validation.php | 2 +- f_func/func.php | 2 +- f_install/_common.php | 2 +- f_install/install1Post.php | 6 +- f_retrival/_common.php | 2 +- i_banner/banner.php | 1 - i_entrance/_common.php | 2 +- i_entrance/adminPost.php | 16 +- i_entrance/donation/Get.php | 2 +- i_entrance/donation/Post.php | 2 +- i_entrance/donation/_common.php | 2 +- i_entrance/donation/calculatePost.php | 2 +- i_entrance/enterPost.php | 2 - i_entrance/logoutPost.php | 2 +- i_entrance/manage/Get.php | 2 +- i_entrance/manage/_common.php | 2 +- i_entrance/manage/deletePost.php | 2 +- i_entrance/manage/iconPost.php | 2 +- i_entrance/manage/passwordPost.php | 2 +- i_entrance/manage/quitPost.php | 2 +- i_entrance/member/Get.php | 2 +- i_entrance/member/Post.php | 2 +- i_entrance/member/_common.php | 2 +- i_entrance/serverListPost.php | 2 +- i_login/Post.php | 2 +- i_login/_common.php | 2 +- i_login/findpw/Get.php | 2 +- i_login/findpw/Post.php | 2 +- i_login/findpw/_common.php | 2 +- i_login/findpw/checkPost.php | 2 +- i_login/findpw/sendCodePost.php | 2 +- i_login/findpw/verifyCodePost.php | 2 +- i_login/join/Get.php | 2 +- i_login/join/_common.php | 2 +- i_login/join/sendCodePost.php | 2 +- i_login/join/verifyCodePost.php | 2 +- i_other/_common.php | 2 +- i_popup/_common.php | 2 +- install.php | 4 +- twe_close/MYDB.php | 1 - twe_close/_119_b.php | 4 +- twe_close/_admin1_submit.php | 4 +- twe_close/_admin2_submit.php | 4 +- twe_close/_admin3_submit.php | 4 +- twe_close/_admin4_submit.php | 4 +- twe_close/_admin5_submit.php | 5 +- twe_close/_simul.php | 2 +- twe_close/a_traffic.php | 2 +- twe_close/a_vote.php | 2 +- twe_close/analytics.php | 3 +- twe_close/c_auction.php | 2 +- twe_close/c_betting.php | 3 +- twe_close/c_chiefboard.php | 4 +- twe_close/c_dipcenter.php | 4 +- twe_close/c_double.php | 1 - twe_close/c_msgsubmit.php | 5 +- twe_close/c_myBossInfo.php | 4 +- twe_close/c_nationboard.php | 3 +- twe_close/c_nationrule.php | 5 +- twe_close/c_tournament.php | 3 +- twe_close/c_troop.php | 2 - twe_close/c_vacation.php | 5 +- twe_close/c_vote.php | 3 +- twe_close/d_ally.php | 2 - twe_close/d_cancel.php | 2 - twe_close/d_cease.php | 2 - twe_close/d_merge.php | 2 - twe_close/d_scout.php | 2 - twe_close/d_setting/_common.php | 1 - twe_close/d_surrender.php | 2 - twe_close/data/connected.php | 2 +- .../session/sess_0g2lnrmd2poc1blmuai0r5vfoq | 2 +- twe_close/event_1.php | 2 - twe_close/event_2.php | 2 - twe_close/event_3.php | 2 - twe_close/event_4.php | 2 - twe_close/func.php | 1 - twe_close/func_auction.php | 1 - twe_close/func_history.php | 1 - twe_close/func_http.php | 1 - twe_close/func_npc.php | 1 - twe_close/func_process.php | 1 - twe_close/func_string.php | 1 - twe_close/install.php | 2 +- twe_close/install2_ok.php | 1 - twe_close/install3_ok.php | 4 +- twe_close/install_ok.php | 5 +- twe_close/join_post.php | 1 - twe_close/join_post.php.orig | 1 - twe_close/join_token.php | 1 - twe_close/lib.php | 3 +- twe_close/license.txt | 37 +- twe_close/login_process.php | 1 - twe_close/logout_process.php | 6 +- twe_close/main.php | 2 - twe_close/map.php | 1 - twe_close/map_history.php | 1 - twe_close/npc_login_process.php | 1 - twe_close/phpinfo.php | 3 - twe_close/preprocessing.php | 2 - twe_close/proc.php | 1 - twe_close/process_war.php | 1 - twe_close/processing.php | 2 - twe_close/queue.php | 1 - twe_close/reset.php | 3 +- twe_close/scenario_1.php | 1 - twe_close/scenario_10.php | 1 - twe_close/scenario_11.php | 1 - twe_close/scenario_12.php | 1 - twe_close/scenario_2.php | 1 - twe_close/scenario_20.php | 1 - twe_close/scenario_21.php | 1 - twe_close/scenario_22.php | 1 - twe_close/scenario_23.php | 1 - twe_close/scenario_24.php | 1 - twe_close/scenario_25.php | 1 - twe_close/scenario_26.php | 1 - twe_close/scenario_27.php | 1 - twe_close/scenario_28.php | 1 - twe_close/scenario_3.php | 1 - twe_close/scenario_4.php | 1 - twe_close/scenario_5.php | 1 - twe_close/scenario_6.php | 1 - twe_close/scenario_7.php | 1 - twe_close/scenario_8.php | 1 - twe_close/scenario_9.php | 1 - twe_close/schema.php | 2 - twe_close/schema.sql.orig | 2 - twe_close/select_npc_post.php | 1 - twe_close/turn.php | 3 - twe_close/turn_pop_core.php | 3 - twe_close/turn_push_core.php | 2 - 231 files changed, 5683 insertions(+), 326 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 che_close/phpinfo.php create mode 100644 e_lib/license.txt create mode 100644 e_lib/src/utilphp/util.php create mode 100644 e_lib/util.php create mode 100644 e_lib/utilphp-1.1.0/.coveralls.yml create mode 100644 e_lib/utilphp-1.1.0/.gitignore create mode 100644 e_lib/utilphp-1.1.0/.travis.yml create mode 100644 e_lib/utilphp-1.1.0/CHANGELOG.md create mode 100644 e_lib/utilphp-1.1.0/CONTRIBUTORS.md create mode 100644 e_lib/utilphp-1.1.0/LICENSE.md create mode 100644 e_lib/utilphp-1.1.0/README.md create mode 100644 e_lib/utilphp-1.1.0/composer.json create mode 100644 e_lib/utilphp-1.1.0/docs/css/docs.css create mode 100644 e_lib/utilphp-1.1.0/docs/favicon.png create mode 100644 e_lib/utilphp-1.1.0/docs/images/awesome_var_dump.jpg create mode 100644 e_lib/utilphp-1.1.0/docs/images/background.png create mode 100644 e_lib/utilphp-1.1.0/docs/images/utility_logo.png create mode 100644 e_lib/utilphp-1.1.0/docs/index.html create mode 100644 e_lib/utilphp-1.1.0/phpunit.xml.dist create mode 100644 e_lib/utilphp-1.1.0/tests/README.md create mode 100644 e_lib/utilphp-1.1.0/tests/UtilTest.php delete mode 100644 twe_close/phpinfo.php diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..7dc85d41 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/logs/*.txt": true, + + }, + "search.exclude": { + "**/che_close": true, + "e_lib/*":true, + }, +} \ No newline at end of file diff --git a/_common.php b/_common.php index bc36bd5c..fecd45f7 100644 --- a/_common.php +++ b/_common.php @@ -7,4 +7,3 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> diff --git a/che_close/_119_b.php b/che_close/_119_b.php index 365c3a7e..ad3027d3 100644 --- a/che_close/_119_b.php +++ b/che_close/_119_b.php @@ -54,4 +54,3 @@ case "락풀기": } echo ""; -?> diff --git a/che_close/_admin1_submit.php b/che_close/_admin1_submit.php index 3f3bd5b2..c48f3ffd 100644 --- a/che_close/_admin1_submit.php +++ b/che_close/_admin1_submit.php @@ -176,5 +176,3 @@ switch($btn) { } echo ""; -?> - diff --git a/che_close/_admin2_submit.php b/che_close/_admin2_submit.php index 295d675e..c08fe206 100644 --- a/che_close/_admin2_submit.php +++ b/che_close/_admin2_submit.php @@ -428,5 +428,4 @@ switch($btn) { } echo ""; -?> diff --git a/che_close/_admin3_submit.php b/che_close/_admin3_submit.php index 60ed41b5..119d7548 100644 --- a/che_close/_admin3_submit.php +++ b/che_close/_admin3_submit.php @@ -130,5 +130,3 @@ switch($btn) { } echo ""; -?> - diff --git a/che_close/_admin4_submit.php b/che_close/_admin4_submit.php index 344f7def..bea27171 100644 --- a/che_close/_admin4_submit.php +++ b/che_close/_admin4_submit.php @@ -103,5 +103,3 @@ switch($btn) { } echo ""; -?> - diff --git a/che_close/_admin5_submit.php b/che_close/_admin5_submit.php index 3a6bcb98..6aa1ea8d 100644 --- a/che_close/_admin5_submit.php +++ b/che_close/_admin5_submit.php @@ -26,5 +26,3 @@ switch($btn) { } echo ""; -?> - diff --git a/che_close/_simul.php b/che_close/_simul.php index b993bd97..5f3b4120 100644 --- a/che_close/_simul.php +++ b/che_close/_simul.php @@ -1559,4 +1559,4 @@ function printSimul($game, $i) { "; } -?> + diff --git a/che_close/a_traffic.php b/che_close/a_traffic.php index 3731917b..1f12bb51 100644 --- a/che_close/a_traffic.php +++ b/che_close/a_traffic.php @@ -254,4 +254,3 @@ function getHexCode($hex) { case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F"; } } -?> diff --git a/che_close/a_vote.php b/che_close/a_vote.php index b6acb56c..b225b11c 100644 --- a/che_close/a_vote.php +++ b/che_close/a_vote.php @@ -335,4 +335,3 @@ function getNewColor($type) { return $color; } -?> diff --git a/che_close/analytics.php b/che_close/analytics.php index bf3f0d19..f0e83ec9 100644 --- a/che_close/analytics.php +++ b/che_close/analytics.php @@ -1,4 +1,4 @@ -"; -?> - diff --git a/che_close/c_double.php b/che_close/c_double.php index 8c99759b..d15b8ce5 100644 --- a/che_close/c_double.php +++ b/che_close/c_double.php @@ -124,5 +124,3 @@ if($command == 46) { echo ""; } -?> - diff --git a/che_close/c_msgsubmit.php b/che_close/c_msgsubmit.php index 4a0eba39..921e575d 100644 --- a/che_close/c_msgsubmit.php +++ b/che_close/c_msgsubmit.php @@ -115,5 +115,3 @@ if($genlist == 9999 && str_replace(" ", "", $msg) != "") { echo ""; -?> - diff --git a/che_close/c_myBossInfo.php b/che_close/c_myBossInfo.php index f12bee51..c4fa16a7 100644 --- a/che_close/c_myBossInfo.php +++ b/che_close/c_myBossInfo.php @@ -252,5 +252,3 @@ if($btn == "추방") { echo ""; -?> - diff --git a/che_close/c_nationrule.php b/che_close/c_nationrule.php index 9744f007..77aeb108 100644 --- a/che_close/c_nationrule.php +++ b/che_close/c_nationrule.php @@ -18,5 +18,3 @@ MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); echo ""; -?> - diff --git a/che_close/c_tournament.php b/che_close/c_tournament.php index 157dc74a..6c1fe646 100644 --- a/che_close/c_tournament.php +++ b/che_close/c_tournament.php @@ -3,6 +3,7 @@ include "lib.php"; include "func.php"; + //로그인 검사 CheckLogin(); $connect = dbConn(); diff --git a/che_close/c_troop.php b/che_close/c_troop.php index 5dbdfb79..0da27a5f 100644 --- a/che_close/c_troop.php +++ b/che_close/c_troop.php @@ -54,5 +54,3 @@ if($btn == "부 대 창 설" && $name != "" && $me[troop] == 0) { echo ""; MYDB_close($connect); -?> - diff --git a/che_close/c_vacation.php b/che_close/c_vacation.php index b4062169..4f161d1b 100644 --- a/che_close/c_vacation.php +++ b/che_close/c_vacation.php @@ -16,5 +16,3 @@ $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"" echo ""; -?> - diff --git a/che_close/config.php b/che_close/config.php index a1daf139..c60c8bb5 100644 --- a/che_close/config.php +++ b/che_close/config.php @@ -1,6 +1,6 @@ - +*/ \ No newline at end of file diff --git a/che_close/d_ally.php b/che_close/d_ally.php index 3e6b36f4..21c29d87 100644 --- a/che_close/d_ally.php +++ b/che_close/d_ally.php @@ -116,5 +116,3 @@ pushGenLog($you, $youlog); echo ""; -?> - diff --git a/che_close/d_cancel.php b/che_close/d_cancel.php index 94281351..7dd03327 100644 --- a/che_close/d_cancel.php +++ b/che_close/d_cancel.php @@ -95,5 +95,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/che_close/d_cease.php b/che_close/d_cease.php index 76c125f7..88dfd30c 100644 --- a/che_close/d_cease.php +++ b/che_close/d_cease.php @@ -100,5 +100,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/che_close/d_merge.php b/che_close/d_merge.php index d57c213e..9a202e95 100644 --- a/che_close/d_merge.php +++ b/che_close/d_merge.php @@ -134,5 +134,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/che_close/d_scout.php b/che_close/d_scout.php index 9900e98f..e427359d 100644 --- a/che_close/d_scout.php +++ b/che_close/d_scout.php @@ -159,6 +159,3 @@ pushAllLog($alllog); pushHistory($connect, $history); echo ""; - -?> - diff --git a/che_close/d_setting/_common.php b/che_close/d_setting/_common.php index 90e4756f..57949e8d 100644 --- a/che_close/d_setting/_common.php +++ b/che_close/d_setting/_common.php @@ -7,4 +7,3 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> diff --git a/che_close/d_surrender.php b/che_close/d_surrender.php index 729fe7fa..d6b37480 100644 --- a/che_close/d_surrender.php +++ b/che_close/d_surrender.php @@ -124,5 +124,4 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/che_close/data/connected.php b/che_close/data/connected.php index caaabefa..6702e873 100644 --- a/che_close/data/connected.php +++ b/che_close/data/connected.php @@ -1 +1 @@ - + - diff --git a/che_close/event_2.php b/che_close/event_2.php index 94bcc518..b104b92b 100644 --- a/che_close/event_2.php +++ b/che_close/event_2.php @@ -253,5 +253,3 @@ function RegGeneral3($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> - diff --git a/che_close/event_3.php b/che_close/event_3.php index 48fd3d51..a613f347 100644 --- a/che_close/event_3.php +++ b/che_close/event_3.php @@ -114,5 +114,3 @@ function RegGeneral3($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> - diff --git a/che_close/event_4.php b/che_close/event_4.php index 9d3b1c10..0b4ec99d 100644 --- a/che_close/event_4.php +++ b/che_close/event_4.php @@ -143,5 +143,3 @@ function RegGeneral4($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> - diff --git a/che_close/func.php b/che_close/func.php index 31577742..7ef2380e 100644 --- a/che_close/func.php +++ b/che_close/func.php @@ -7416,4 +7416,3 @@ function Submit($url, $msg="", $msg2="") { "; } -?> diff --git a/che_close/func_auction.php b/che_close/func_auction.php index 9ffd729c..065d6919 100644 --- a/che_close/func_auction.php +++ b/che_close/func_auction.php @@ -345,4 +345,3 @@ function processAuction($connect) { MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/che_close/func_history.php b/che_close/func_history.php index bd18360c..210eca7c 100644 --- a/che_close/func_history.php +++ b/che_close/func_history.php @@ -128,4 +128,3 @@ function LogHistory($connect, $isFirst=0) { if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', LogHistory Finish'); return true; } -?> diff --git a/che_close/func_http.php b/che_close/func_http.php index 09dd69d3..c809b579 100644 --- a/che_close/func_http.php +++ b/che_close/func_http.php @@ -285,4 +285,3 @@ class HTTP{ } } } -?> \ No newline at end of file diff --git a/che_close/func_npc.php b/che_close/func_npc.php index 9c8f7d1d..c1444023 100644 --- a/che_close/func_npc.php +++ b/che_close/func_npc.php @@ -1861,4 +1861,3 @@ function RiceBillRate($connect, $nation, $rate, $rice_rate, $type, $rice) { MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/che_close/func_process.php b/che_close/func_process.php index 7c25f4ff..abcc8493 100644 --- a/che_close/func_process.php +++ b/che_close/func_process.php @@ -6145,4 +6145,3 @@ function process_99($connect, &$general) { pushGenLog($general, $log); } -?> diff --git a/che_close/func_string.php b/che_close/func_string.php index 6c8c0c27..c84011af 100644 --- a/che_close/func_string.php +++ b/che_close/func_string.php @@ -301,4 +301,3 @@ class _String { } } -?> diff --git a/che_close/install2_ok.php b/che_close/install2_ok.php index 9c83711c..1441a8a7 100644 --- a/che_close/install2_ok.php +++ b/che_close/install2_ok.php @@ -345,4 +345,3 @@ function insertCity($connect, $name, $level, $pop2, $agri2, $comm2, $secu2, $def ) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/che_close/install3_ok.php b/che_close/install3_ok.php index 3d4f74b0..4a5fd495 100644 --- a/che_close/install3_ok.php +++ b/che_close/install3_ok.php @@ -6,5 +6,5 @@ $connect=dbConn(); LogHistory($connect, 1); -echo ""; -?> +//echo ""; +echo "index.php"; //TODO:replace diff --git a/che_close/install_ok.php b/che_close/install_ok.php index 3d0326c3..9ae5d345 100644 --- a/che_close/install_ok.php +++ b/che_close/install_ok.php @@ -83,7 +83,7 @@ if(!isTable($connect, "history",$dbname)) @MYDB_query($history_schema, $connect) // 파일로 DB 정보 저장 $file=@fopen("d_setting/set.php","w") or Error("set.php 파일 생성 실패

디렉토리의 퍼미션을 707로 주십시요",""); -@fwrite($file,"\n") or Error("set.php 파일 생성 실패

디렉토리의 퍼미션을 707로 주십시요",""); +@fwrite($file,"
디렉토리의 퍼미션을 707로 주십시요",""); @fclose($file); @mkdir("data",0707); @chmod("data",0707); @@ -93,5 +93,4 @@ $temp=MYDB_fetch_array(MYDB_query("select count(*) from general where level = '1 MYDB_close($connect); -echo ""; -?> +echo "install2.php"; //TODO:location.replace 살려두기 diff --git a/che_close/join_post.php b/che_close/join_post.php index 52384fb3..52d6e10f 100644 --- a/che_close/join_post.php +++ b/che_close/join_post.php @@ -271,5 +271,3 @@ if($id_num) { "); echo(""); } - -?> diff --git a/che_close/join_post.php.orig b/che_close/join_post.php.orig index ed10c24b..c796b36b 100644 --- a/che_close/join_post.php.orig +++ b/che_close/join_post.php.orig @@ -272,4 +272,3 @@ if($id_num) { echo(""); } -?> diff --git a/che_close/join_token.php b/che_close/join_token.php index 87042ec3..992b5b88 100644 --- a/che_close/join_token.php +++ b/che_close/join_token.php @@ -54,5 +54,3 @@ $response['intel'] = $abil['intel']; usleep(100*1000); echo json_encode($response); - -?> \ No newline at end of file diff --git a/che_close/lib.php b/che_close/lib.php index 7166d844..f6159ad3 100644 --- a/che_close/lib.php +++ b/che_close/lib.php @@ -181,4 +181,3 @@ function PrintElapsedTime() { $_endTime = round(getMicroTime() - $_startTime, 3); echo "
경과시간 : {$_endTime}초
"; } -?> diff --git a/che_close/login_process.php b/che_close/login_process.php index 1129f3c1..a3d56c76 100644 --- a/che_close/login_process.php +++ b/che_close/login_process.php @@ -78,4 +78,3 @@ function DeleteSession() { } MYDB_close($connect); -?> diff --git a/che_close/logout_process.php b/che_close/logout_process.php index 17b57479..ba8f1379 100644 --- a/che_close/logout_process.php +++ b/che_close/logout_process.php @@ -16,7 +16,7 @@ $id = $me[user_id]; $pw = $me[password]; $conmsg = $me[conmsg]; -//Ǻ +//���Ǻ��� ���� session_destroy(); echo ""; @@ -33,4 +33,3 @@ a */ -?> diff --git a/che_close/phpinfo.php b/che_close/phpinfo.php deleted file mode 100644 index cf608608..00000000 --- a/che_close/phpinfo.php +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/d_setting/_common.php b/d_setting/_common.php index cea1c49d..25378505 100644 --- a/d_setting/_common.php +++ b/d_setting/_common.php @@ -7,4 +7,3 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> diff --git a/d_setting/set.php b/d_setting/set.php index f941935e..1cba5893 100644 --- a/d_setting/set.php +++ b/d_setting/set.php @@ -8,4 +8,4 @@ smtp.gmail.com aser ewrwer @gmail.com - */?> + */ diff --git a/e_lib/license.txt b/e_lib/license.txt new file mode 100644 index 00000000..36931abb --- /dev/null +++ b/e_lib/license.txt @@ -0,0 +1 @@ +TODO : adobdb5, phpmailer5(?), plates, utilphp \ No newline at end of file diff --git a/e_lib/meekrodb.2.3.class.php b/e_lib/meekrodb.2.3.class.php index e63d9669..93cba614 100644 --- a/e_lib/meekrodb.2.3.class.php +++ b/e_lib/meekrodb.2.3.class.php @@ -953,4 +953,4 @@ class MeekroDBEval { } } -?> + diff --git a/e_lib/phpmailer5/class.phpmailer.php b/e_lib/phpmailer5/class.phpmailer.php index 4589cd79..2b994574 100644 --- a/e_lib/phpmailer5/class.phpmailer.php +++ b/e_lib/phpmailer5/class.phpmailer.php @@ -2470,4 +2470,4 @@ class phpmailerException extends Exception { return $errorMsg; } } -?> + diff --git a/e_lib/phpmailer5/class.pop3.php b/e_lib/phpmailer5/class.pop3.php index 83df20f3..d15db74c 100644 --- a/e_lib/phpmailer5/class.pop3.php +++ b/e_lib/phpmailer5/class.pop3.php @@ -407,4 +407,4 @@ class POP3 { // End of class } -?> + diff --git a/e_lib/phpmailer5/class.smtp.php b/e_lib/phpmailer5/class.smtp.php index 07c27593..5254943e 100644 --- a/e_lib/phpmailer5/class.smtp.php +++ b/e_lib/phpmailer5/class.smtp.php @@ -814,4 +814,4 @@ class SMTP { } -?> + diff --git a/e_lib/src/utilphp/util.php b/e_lib/src/utilphp/util.php new file mode 100644 index 00000000..0932d7d1 --- /dev/null +++ b/e_lib/src/utilphp/util.php @@ -0,0 +1,2535 @@ + + * @link http://github.com/brandonwamboldt/utilphp/ Official Documentation + */ +class util +{ + /** + * A constant representing the number of seconds in a minute, for + * making code more verbose + * + * @var integer + */ + const SECONDS_IN_A_MINUTE = 60; + + /** + * A constant representing the number of seconds in an hour, for making + * code more verbose + * + * @var integer + */ + const SECONDS_IN_A_HOUR = 3600; + const SECONDS_IN_AN_HOUR = 3600; + + /** + * A constant representing the number of seconds in a day, for making + * code more verbose + * + * @var integer + */ + const SECONDS_IN_A_DAY = 86400; + + /** + * A constant representing the number of seconds in a week, for making + * code more verbose + * + * @var integer + */ + const SECONDS_IN_A_WEEK = 604800; + + /** + * A constant representing the number of seconds in a month (30 days), + * for making code more verbose + * + * @var integer + */ + const SECONDS_IN_A_MONTH = 2592000; + + /** + * A constant representing the number of seconds in a year (365 days), + * for making code more verbose + * + * @var integer + */ + const SECONDS_IN_A_YEAR = 31536000; + + /** + * URL constants as defined in the PHP Manual under "Constants usable with + * http_build_url()". + * + * @see http://us2.php.net/manual/en/http.constants.php#http.constants.url + */ + const HTTP_URL_REPLACE = 1; + const HTTP_URL_JOIN_PATH = 2; + const HTTP_URL_JOIN_QUERY = 4; + const HTTP_URL_STRIP_USER = 8; + const HTTP_URL_STRIP_PASS = 16; + const HTTP_URL_STRIP_AUTH = 32; + const HTTP_URL_STRIP_PORT = 64; + const HTTP_URL_STRIP_PATH = 128; + const HTTP_URL_STRIP_QUERY = 256; + const HTTP_URL_STRIP_FRAGMENT = 512; + const HTTP_URL_STRIP_ALL = 1024; + + /** + * A collapse icon, using in the dump_var function to allow collapsing + * an array or object + * + * @var string + */ + public static $icon_collapse = 'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAMAAADXT/YiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MjlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNzFDNDQyNEMyQzkxMUUxOTU4MEM4M0UxRDA0MUVGNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNzFDNDQyM0MyQzkxMUUxOTU4MEM4M0UxRDA0MUVGNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NDlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MjlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuF4AWkAAAA2UExURU9t2DBStczM/1h16DNmzHiW7iNFrypMvrnD52yJ4ezs7Onp6ejo6P///+Tk5GSG7D9h5SRGq0Q2K74AAAA/SURBVHjaLMhZDsAgDANRY3ZISnP/y1ZWeV+jAeuRSky6cKL4ryDdSggP8UC7r6GvR1YHxjazPQDmVzI/AQYAnFQDdVSJ80EAAAAASUVORK5CYII='; + + /** + * A collapse icon, using in the dump_var function to allow collapsing + * an array or object + * + * @var string + */ + public static $icon_expand = 'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAMAAADXT/YiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MTlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFQzZERTJDNEMyQzkxMUUxODRCQzgyRUNDMzZEQkZFQiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFQzZERTJDM0MyQzkxMUUxODRCQzgyRUNDMzZEQkZFQiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3MzlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MTlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkmDvWIAAABIUExURU9t2MzM/3iW7ubm59/f5urq85mZzOvr6////9ra38zMzObm5rfB8FZz5myJ4SNFrypMvjBStTNmzOvr+mSG7OXl8T9h5SRGq/OfqCEAAABKSURBVHjaFMlbEoAwCEPRULXF2jdW9r9T4czcyUdA4XWB0IgdNSybxU9amMzHzDlPKKu7Fd1e6+wY195jW0ARYZECxPq5Gn8BBgCr0gQmxpjKAwAAAABJRU5ErkJggg=='; + + private static $hasArray = false; + + /** + * Map of special non-ASCII characters and suitable ASCII replacement + * characters. + * + * Part of the URLify.php Project + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + */ + public static $maps = array( + 'de' => array(/* German */ + 'Ä' => 'Ae', 'Ö' => 'Oe', 'Ü' => 'Ue', 'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'ß' => 'ss', + 'ẞ' => 'SS' + ), + 'latin' => array( + 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A','Ă' => 'A', 'Æ' => 'AE', 'Ç' => + 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', + 'Ï' => 'I', 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => + 'O', 'Ő' => 'O', 'Ø' => 'O','Ș' => 'S','Ț' => 'T', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', + 'Ý' => 'Y', 'Þ' => 'TH', 'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => + 'a', 'å' => 'a', 'ă' => 'a', 'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', + 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => + 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', 'ø' => 'o', 'ș' => 's', 'ț' => 't', 'ù' => 'u', 'ú' => 'u', + 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', 'ÿ' => 'y' + ), + 'latin_symbols' => array( + '©' => '(c)' + ), + 'el' => array(/* Greek */ + 'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8', + 'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p', + 'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w', + 'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's', + 'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i', + 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8', + 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P', + 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W', + 'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I', + 'Ϋ' => 'Y' + ), + 'tr' => array(/* Turkish */ + 'ş' => 's', 'Ş' => 'S', 'ı' => 'i', 'İ' => 'I', 'ç' => 'c', 'Ç' => 'C', 'ü' => 'u', 'Ü' => 'U', + 'ö' => 'o', 'Ö' => 'O', 'ğ' => 'g', 'Ğ' => 'G' + ), + 'ru' => array(/* Russian */ + 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh', + 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', + 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', + 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', + 'я' => 'ya', + 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh', + 'З' => 'Z', 'И' => 'I', 'Й' => 'J', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', + 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', + 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu', + 'Я' => 'Ya', + '№' => '' + ), + 'uk' => array(/* Ukrainian */ + 'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g' + ), + 'cs' => array(/* Czech */ + 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u', + 'ž' => 'z', 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T', + 'Ů' => 'U', 'Ž' => 'Z' + ), + 'pl' => array(/* Polish */ + 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z', + 'ż' => 'z', 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'O', 'Ś' => 'S', + 'Ź' => 'Z', 'Ż' => 'Z' + ), + 'ro' => array(/* Romanian */ + 'ă' => 'a', 'â' => 'a', 'î' => 'i', 'ș' => 's', 'ț' => 't', 'Ţ' => 'T', 'ţ' => 't' + ), + 'lv' => array(/* Latvian */ + 'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', + 'š' => 's', 'ū' => 'u', 'ž' => 'z', 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', + 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z' + ), + 'lt' => array(/* Lithuanian */ + 'ą' => 'a', 'č' => 'c', 'ę' => 'e', 'ė' => 'e', 'į' => 'i', 'š' => 's', 'ų' => 'u', 'ū' => 'u', 'ž' => 'z', + 'Ą' => 'A', 'Č' => 'C', 'Ę' => 'E', 'Ė' => 'E', 'Į' => 'I', 'Š' => 'S', 'Ų' => 'U', 'Ū' => 'U', 'Ž' => 'Z' + ), + 'vn' => array(/* Vietnamese */ + 'Á' => 'A', 'À' => 'A', 'Ả' => 'A', 'Ã' => 'A', 'Ạ' => 'A', 'Ă' => 'A', 'Ắ' => 'A', 'Ằ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ặ' => 'A', 'Â' => 'A', 'Ấ' => 'A', 'Ầ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ậ' => 'A', + 'á' => 'a', 'à' => 'a', 'ả' => 'a', 'ã' => 'a', 'ạ' => 'a', 'ă' => 'a', 'ắ' => 'a', 'ằ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ặ' => 'a', 'â' => 'a', 'ấ' => 'a', 'ầ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ậ' => 'a', + 'É' => 'E', 'È' => 'E', 'Ẻ' => 'E', 'Ẽ' => 'E', 'Ẹ' => 'E', 'Ê' => 'E', 'Ế' => 'E', 'Ề' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ệ' => 'E', + 'é' => 'e', 'è' => 'e', 'ẻ' => 'e', 'ẽ' => 'e', 'ẹ' => 'e', 'ê' => 'e', 'ế' => 'e', 'ề' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ệ' => 'e', + 'Í' => 'I', 'Ì' => 'I', 'Ỉ' => 'I', 'Ĩ' => 'I', 'Ị' => 'I', 'í' => 'i', 'ì' => 'i', 'ỉ' => 'i', 'ĩ' => 'i', 'ị' => 'i', + 'Ó' => 'O', 'Ò' => 'O', 'Ỏ' => 'O', 'Õ' => 'O', 'Ọ' => 'O', 'Ô' => 'O', 'Ố' => 'O', 'Ồ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ộ' => 'O', 'Ơ' => 'O', 'Ớ' => 'O', 'Ờ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ợ' => 'O', + 'ó' => 'o', 'ò' => 'o', 'ỏ' => 'o', 'õ' => 'o', 'ọ' => 'o', 'ô' => 'o', 'ố' => 'o', 'ồ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ộ' => 'o', 'ơ' => 'o', 'ớ' => 'o', 'ờ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ợ' => 'o', + 'Ú' => 'U', 'Ù' => 'U', 'Ủ' => 'U', 'Ũ' => 'U', 'Ụ' => 'U', 'Ư' => 'U', 'Ứ' => 'U', 'Ừ' => 'U', 'Ử' => 'U', 'Ữ' => 'U', 'Ự' => 'U', + 'ú' => 'u', 'ù' => 'u', 'ủ' => 'u', 'ũ' => 'u', 'ụ' => 'u', 'ư' => 'u', 'ứ' => 'u', 'ừ' => 'u', 'ử' => 'u', 'ữ' => 'u', 'ự' => 'u', + 'Ý' => 'Y', 'Ỳ' => 'Y', 'Ỷ' => 'Y', 'Ỹ' => 'Y', 'Ỵ' => 'Y', 'ý' => 'y', 'ỳ' => 'y', 'ỷ' => 'y', 'ỹ' => 'y', 'ỵ' => 'y', + 'Đ' => 'D', 'đ' => 'd' + ), + 'ar' => array(/* Arabic */ + 'أ' => 'a', 'ب' => 'b', 'ت' => 't', 'ث' => 'th', 'ج' => 'g', 'ح' => 'h', 'خ' => 'kh', 'د' => 'd', + 'ذ' => 'th', 'ر' => 'r', 'ز' => 'z', 'س' => 's', 'ش' => 'sh', 'ص' => 's', 'ض' => 'd', 'ط' => 't', + 'ظ' => 'th', 'ع' => 'aa', 'غ' => 'gh', 'ف' => 'f', 'ق' => 'k', 'ك' => 'k', 'ل' => 'l', 'م' => 'm', + 'ن' => 'n', 'ه' => 'h', 'و' => 'o', 'ي' => 'y' + ), + 'sr' => array(/* Serbian */ + 'ђ' => 'dj', 'ј' => 'j', 'љ' => 'lj', 'њ' => 'nj', 'ћ' => 'c', 'џ' => 'dz', 'đ' => 'dj', + 'Ђ' => 'Dj', 'Ј' => 'j', 'Љ' => 'Lj', 'Њ' => 'Nj', 'Ћ' => 'C', 'Џ' => 'Dz', 'Đ' => 'Dj' + ), + 'az' => array(/* Azerbaijani */ + 'ç' => 'c', 'ə' => 'e', 'ğ' => 'g', 'ı' => 'i', 'ö' => 'o', 'ş' => 's', 'ü' => 'u', + 'Ç' => 'C', 'Ə' => 'E', 'Ğ' => 'G', 'İ' => 'I', 'Ö' => 'O', 'Ş' => 'S', 'Ü' => 'U' + ), + ); + + /** + * The character map for the designated language + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + */ + private static $map = array(); + + /** + * The character list as a string. + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + */ + private static $chars = ''; + + /** + * The character list as a regular expression. + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + */ + private static $regex = ''; + + /** + * The current language + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + */ + private static $language = ''; + + /** + * Initializes the character map. + * + * Part of the URLify.php Project + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + */ + private static function initLanguageMap($language = '') + { + if (count(self::$map) > 0 && (($language == '') || ($language == self::$language))) { + return; + } + + // Is a specific map associated with $language? + if (isset(self::$maps[$language]) && is_array(self::$maps[$language])) { + // Move this map to end. This means it will have priority over others + $m = self::$maps[$language]; + unset(self::$maps[$language]); + self::$maps[$language] = $m; + } + + // Reset static vars + self::$language = $language; + self::$map = array(); + self::$chars = ''; + + foreach (self::$maps as $map) { + foreach ($map as $orig => $conv) { + self::$map[$orig] = $conv; + self::$chars .= $orig; + } + } + + self::$regex = '/[' . self::$chars . ']/u'; + } + + + /** + * Access an array index, retrieving the value stored there if it + * exists or a default if it does not. This function allows you to + * concisely access an index which may or may not exist without + * raising a warning. + * + * @param array $var Array value to access + * @param mixed $default Default value to return if the key is not + * present in the array + * @return mixed + */ + public static function array_get(&$var, $default = null) + { + if (isset($var)) { + return $var; + } + + return $default; + } + + /** + * Display a variable's contents using nice HTML formatting and will + * properly display the value of booleans as true or false + * + * @see var_dump_plain() + * + * @param mixed $var The variable to dump + * @return string + */ + public static function var_dump($var, $return = false, $expandLevel = 1) + { + self::$hasArray = false; + $toggScript = 'var colToggle = function(toggID) {var img = document.getElementById(toggID);if (document.getElementById(toggID + "-collapsable").style.display == "none") {document.getElementById(toggID + "-collapsable").style.display = "inline";setImg(toggID, 0);var previousSibling = document.getElementById(toggID + "-collapsable").previousSibling;while (previousSibling != null && (previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br")) {previousSibling = previousSibling.previousSibling;}} else {document.getElementById(toggID + "-collapsable").style.display = "none";setImg(toggID, 1);var previousSibling = document.getElementById(toggID + "-collapsable").previousSibling; while (previousSibling != null && (previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br")) {previousSibling = previousSibling.previousSibling;}}};'; + $imgScript = 'var setImg = function(objID,imgID,addStyle) {var imgStore = ["data:image/png;base64,' . self::$icon_collapse . '", "data:image/png;base64,' . self::$icon_expand . '"];if (objID) {document.getElementById(objID).setAttribute("src", imgStore[imgID]);if (addStyle){document.getElementById(objID).setAttribute("style", "position:relative;left:-5px;top:-1px;cursor:pointer;");}}};'; + $jsCode = preg_replace('/ +/', ' ', ''); + $html = '
';
+        $done  = array();
+        $html .= self::var_dump_plain($var, intval($expandLevel), 0, $done);
+        $html .= '
'; + + if (self::$hasArray) { + $html = $jsCode . $html; + } + + if (!$return) { + echo $html; + } + + return $html; + } + + /** + * Display a variable's contents using nice HTML formatting (Without + * the
 tag) and will properly display the values of variables
+     * like booleans and resources. Supports collapsable arrays and objects
+     * as well.
+     *
+     * @param  mixed $var The variable to dump
+     * @return string
+     */
+    public static function var_dump_plain($var, $expLevel, $depth = 0, $done = array())
+    {
+        $html = '';
+
+        if ($expLevel > 0) {
+            $expLevel--;
+            $setImg = 0;
+            $setStyle = 'display:inline;';
+        } elseif ($expLevel == 0) {
+            $setImg = 1;
+            $setStyle='display:none;';
+        } elseif ($expLevel < 0) {
+            $setImg = 0;
+            $setStyle = 'display:inline;';
+        }
+
+        if (is_bool($var)) {
+            $html .= 'bool(' . (($var) ? 'true' : 'false') . ')';
+        } elseif (is_int($var)) {
+            $html .= 'int(' . $var . ')';
+        } elseif (is_float($var)) {
+            $html .= 'float(' . $var . ')';
+        } elseif (is_string($var)) {
+            $html .= 'string(' . strlen($var) . ') "' . self::htmlentities($var) . '"';
+        } elseif (is_null($var)) {
+            $html .= 'NULL';
+        } elseif (is_resource($var)) {
+            $html .= 'resource("' . get_resource_type($var) . '") "' . $var . '"';
+        } elseif (is_array($var)) {
+            // Check for recursion
+            if ($depth > 0) {
+                foreach ($done as $prev) {
+                    if ($prev === $var) {
+                        $html .= 'array(' . count($var) . ') *RECURSION DETECTED*';
+                        return $html;
+                    }
+                }
+
+                // Keep track of variables we have already processed to detect recursion
+                $done[] = &$var;
+            }
+
+            self::$hasArray = true;
+            $uuid = 'include-php-' . uniqid() . mt_rand(1, 1000000);
+
+            $html .= (!empty($var) ? ' ' : '') . 'array(' . count($var) . ')';
+            if (!empty($var)) {
+                $html .= ' 
[
'; + + $indent = 4; + $longest_key = 0; + + foreach ($var as $key => $value) { + if (is_string($key)) { + $longest_key = max($longest_key, strlen($key) + 2); + } else { + $longest_key = max($longest_key, strlen($key)); + } + } + + foreach ($var as $key => $value) { + if (is_numeric($key)) { + $html .= str_repeat(' ', $indent) . str_pad($key, $longest_key, ' '); + } else { + $html .= str_repeat(' ', $indent) . str_pad('"' . self::htmlentities($key) . '"', $longest_key, ' '); + } + + $html .= ' => '; + + $value = explode('
', self::var_dump_plain($value, $expLevel, $depth + 1, $done)); + + foreach ($value as $line => $val) { + if ($line != 0) { + $value[$line] = str_repeat(' ', $indent * 2) . $val; + } + } + + $html .= implode('
', $value) . '
'; + } + + $html .= ']
'; + } + } elseif (is_object($var)) { + // Check for recursion + foreach ($done as $prev) { + if ($prev === $var) { + $html .= 'object(' . get_class($var) . ') *RECURSION DETECTED*'; + return $html; + } + } + + // Keep track of variables we have already processed to detect recursion + $done[] = &$var; + + self::$hasArray=true; + $uuid = 'include-php-' . uniqid() . mt_rand(1, 1000000); + + $html .= ' object(' . get_class($var) . ')
[
'; + + $varArray = (array) $var; + + $indent = 4; + $longest_key = 0; + + foreach ($varArray as $key => $value) { + if (substr($key, 0, 2) == "\0*") { + unset($varArray[$key]); + $key = 'protected:' . substr($key, 3); + $varArray[$key] = $value; + } elseif (substr($key, 0, 1) == "\0") { + unset($varArray[$key]); + $key = 'private:' . substr($key, 1, strpos(substr($key, 1), "\0")) . ':' . substr($key, strpos(substr($key, 1), "\0") + 2); + $varArray[$key] = $value; + } + + if (is_string($key)) { + $longest_key = max($longest_key, strlen($key) + 2); + } else { + $longest_key = max($longest_key, strlen($key)); + } + } + + foreach ($varArray as $key => $value) { + if (is_numeric($key)) { + $html .= str_repeat(' ', $indent) . str_pad($key, $longest_key, ' '); + } else { + $html .= str_repeat(' ', $indent) . str_pad('"' . self::htmlentities($key) . '"', $longest_key, ' '); + } + + $html .= ' => '; + + $value = explode('
', self::var_dump_plain($value, $expLevel, $depth + 1, $done)); + + foreach ($value as $line => $val) { + if ($line != 0) { + $value[$line] = str_repeat(' ', $indent * 2) . $val; + } + } + + $html .= implode('
', $value) . '
'; + } + + $html .= ']
'; + } + + return $html; + } + + /** + * Converts any accent characters to their equivalent normal characters + * and converts any other non-alphanumeric characters to dashes, then + * converts any sequence of two or more dashes to a single dash. This + * function generates slugs safe for use as URLs, and if you pass true + * as the second parameter, it will create strings safe for use as CSS + * classes or IDs. + * + * @param string $string A string to convert to a slug + * @param string $separator The string to separate words with + * @param boolean $css_mode Whether or not to generate strings safe for + * CSS classes/IDs (Default to false) + * @return string + */ + public static function slugify($string, $separator = '-', $css_mode = false) + { + // Compatibility with 1.0.* parameter ordering for semvar + if ($separator === true || $separator === false) { + $css_mode = $separator; + $separator = '-'; + + // Raise deprecation error + trigger_error( + 'util::slugify() now takes $css_mode as the third parameter, please update your code', + E_USER_DEPRECATED + ); + } + + $slug = preg_replace('/([^a-z0-9]+)/', $separator, strtolower(self::remove_accents($string))); + + if ($css_mode) { + $digits = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'); + + if (is_numeric(substr($slug, 0, 1))) { + $slug = $digits[substr($slug, 0, 1)] . substr($slug, 1); + } + } + + return $slug; + } + + /** + * Checks to see if a string is utf8 encoded. + * + * NOTE: This function checks for 5-Byte sequences, UTF8 + * has Bytes Sequences with a maximum length of 4. + * + * Written by Tony Ferrara + * + * @param string $string The string to be checked + * @return boolean + */ + public static function seems_utf8($string) + { + if (function_exists('mb_check_encoding')) { + // If mbstring is available, this is significantly faster than + // using PHP regexps. + return mb_check_encoding($string, 'UTF-8'); + } + + // @codeCoverageIgnoreStart + return self::seemsUtf8Regex($string); + // @codeCoverageIgnoreEnd + } + + /** + * A non-Mbstring UTF-8 checker. + * + * @param $string + * @return bool + */ + protected static function seemsUtf8Regex($string) + { + // Obtained from http://stackoverflow.com/a/11709412/430062 with permission. + $regex = '/( + [\xC0-\xC1] # Invalid UTF-8 Bytes + | [\xF5-\xFF] # Invalid UTF-8 Bytes + | \xE0[\x80-\x9F] # Overlong encoding of prior code point + | \xF0[\x80-\x8F] # Overlong encoding of prior code point + | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start + | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start + | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start + | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle + | (? + * + * @param string $brokenSerializedData + * @return string + */ + public static function fix_broken_serialization($brokenSerializedData) + { + $fixdSerializedData = preg_replace_callback('!s:(\d+):"(.*?)";!', function($matches) { + $snip = $matches[2]; + return 's:' . strlen($snip) . ':"' . $snip . '";'; + }, $brokenSerializedData); + + return $fixdSerializedData; + } + + /** + * Checks to see if the page is being server over SSL or not + * + * @return boolean + */ + public static function is_https() + { + return isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off'; + } + + /** + * Add or remove query arguments to the URL. + * + * @param mixed $newKey Either newkey or an associative array + * @param mixed $newValue Either newvalue or oldquery or uri + * @param mixed $uri URI or URL to append the queru/queries to. + * @return string + */ + public static function add_query_arg($newKey, $newValue = null, $uri = null) + { + // Was an associative array of key => value pairs passed? + if (is_array($newKey)) { + $newParams = $newKey; + + // Was the URL passed as an argument? + if (!is_null($newValue)) { + $uri = $newValue; + } elseif (!is_null($uri)) { + $uri = $uri; + } else { + $uri = self::array_get($_SERVER['REQUEST_URI'], ''); + } + } else { + $newParams = array($newKey => $newValue); + + // Was the URL passed as an argument? + $uri = is_null($uri) ? self::array_get($_SERVER['REQUEST_URI'], '') : $uri; + } + + // Parse the URI into it's components + $puri = parse_url($uri); + + if (isset($puri['query'])) { + parse_str($puri['query'], $queryParams); + $queryParams = array_merge($queryParams, $newParams); + } elseif (isset($puri['path']) && strstr($puri['path'], '=') !== false) { + $puri['query'] = $puri['path']; + unset($puri['path']); + parse_str($puri['query'], $queryParams); + $queryParams = array_merge($queryParams, $newParams); + } else { + $queryParams = $newParams; + } + + // Strip out any query params that are set to false + foreach ($queryParams as $param => $value) { + if ($value === false) { + unset($queryParams[$param]); + } + } + + // Re-construct the query string + $puri['query'] = http_build_query($queryParams); + + // Re-construct the entire URL + $nuri = self::http_build_url($puri); + + // Make the URI consistent with our input + if ($nuri[0] === '/' && strstr($uri, '/') === false) { + $nuri = substr($nuri, 1); + } + + if ($nuri[0] === '?' && strstr($uri, '?') === false) { + $nuri = substr($nuri, 1); + } + + return rtrim($nuri, '?'); + } + + /** + * Removes an item or list from the query string. + * + * @param string|array $keys Query key or keys to remove. + * @param bool $uri When false uses the $_SERVER value + * @return string + */ + public static function remove_query_arg($keys, $uri = null) + { + if (is_array($keys)) { + return self::add_query_arg(array_combine($keys, array_fill(0, count($keys), null)), $uri); + } + + return self::add_query_arg(array($keys => null), $uri); + } + + /** + * Build a URL. + * + * The parts of the second URL will be merged into the first according to + * the flags argument. + * + * @author Jake Smith + * @see https://github.com/jakeasmith/http_build_url/ + * + * @param mixed $url (part(s) of) an URL in form of a string or + * associative array like parse_url() returns + * @param mixed $parts same as the first argument + * @param int $flags a bitmask of binary or'ed HTTP_URL constants; + * HTTP_URL_REPLACE is the default + * @param array $new_url if set, it will be filled with the parts of the + * composed url like parse_url() would return + * @return string + */ + public static function http_build_url($url, $parts = array(), $flags = self::HTTP_URL_REPLACE, &$new_url = array()) + { + is_array($url) || $url = parse_url($url); + is_array($parts) || $parts = parse_url($parts); + + isset($url['query']) && is_string($url['query']) || $url['query'] = null; + isset($parts['query']) && is_string($parts['query']) || $parts['query'] = null; + + $keys = array('user', 'pass', 'port', 'path', 'query', 'fragment'); + + // HTTP_URL_STRIP_ALL and HTTP_URL_STRIP_AUTH cover several other flags. + if ($flags & self::HTTP_URL_STRIP_ALL) { + $flags |= self::HTTP_URL_STRIP_USER | self::HTTP_URL_STRIP_PASS + | self::HTTP_URL_STRIP_PORT | self::HTTP_URL_STRIP_PATH + | self::HTTP_URL_STRIP_QUERY | self::HTTP_URL_STRIP_FRAGMENT; + } elseif ($flags & self::HTTP_URL_STRIP_AUTH) { + $flags |= self::HTTP_URL_STRIP_USER | self::HTTP_URL_STRIP_PASS; + } + + // Schema and host are alwasy replaced + foreach (array('scheme', 'host') as $part) { + if (isset($parts[$part])) { + $url[$part] = $parts[$part]; + } + } + + if ($flags & self::HTTP_URL_REPLACE) { + foreach ($keys as $key) { + if (isset($parts[$key])) { + $url[$key] = $parts[$key]; + } + } + } else { + if (isset($parts['path']) && ($flags & self::HTTP_URL_JOIN_PATH)) { + if (isset($url['path']) && substr($parts['path'], 0, 1) !== '/') { + $url['path'] = rtrim( + str_replace(basename($url['path']), '', $url['path']), + '/' + ) . '/' . ltrim($parts['path'], '/'); + } else { + $url['path'] = $parts['path']; + } + } + + if (isset($parts['query']) && ($flags & self::HTTP_URL_JOIN_QUERY)) { + if (isset($url['query'])) { + parse_str($url['query'], $url_query); + parse_str($parts['query'], $parts_query); + + $url['query'] = http_build_query( + array_replace_recursive( + $url_query, + $parts_query + ) + ); + } else { + $url['query'] = $parts['query']; + } + } + } + + if (isset($url['path']) && substr($url['path'], 0, 1) !== '/') { + $url['path'] = '/' . $url['path']; + } + + foreach ($keys as $key) { + $strip = 'HTTP_URL_STRIP_' . strtoupper($key); + if ($flags & constant('utilphp\\util::' . $strip)) { + unset($url[$key]); + } + } + + $parsed_string = ''; + + if (isset($url['scheme'])) { + $parsed_string .= $url['scheme'] . '://'; + } + + if (isset($url['user'])) { + $parsed_string .= $url['user']; + + if (isset($url['pass'])) { + $parsed_string .= ':' . $url['pass']; + } + + $parsed_string .= '@'; + } + + if (isset($url['host'])) { + $parsed_string .= $url['host']; + } + + if (isset($url['port'])) { + $parsed_string .= ':' . $url['port']; + } + + if (!empty($url['path'])) { + $parsed_string .= $url['path']; + } else { + $parsed_string .= '/'; + } + + if (isset($url['query'])) { + $parsed_string .= '?' . $url['query']; + } + + if (isset($url['fragment'])) { + $parsed_string .= '#' . $url['fragment']; + } + + $new_url = $url; + + return $parsed_string; + } + + /** + * Converts many english words that equate to true or false to boolean. + * + * Supports 'y', 'n', 'yes', 'no' and a few other variations. + * + * @param string $string The string to convert to boolean + * @param bool $default The value to return if we can't match any + * yes/no words + * @return boolean + */ + public static function str_to_bool($string, $default = false) + { + $yes_words = 'affirmative|all right|aye|indubitably|most assuredly|ok|of course|okay|sure thing|y|yes+|yea|yep|sure|yeah|true|t|on|1|oui|vrai'; + $no_words = 'no*|no way|nope|nah|na|never|absolutely not|by no means|negative|never ever|false|f|off|0|non|faux'; + + if (preg_match('/^(' . $yes_words . ')$/i', $string)) { + return true; + } elseif (preg_match('/^(' . $no_words . ')$/i', $string)) { + return false; + } + + return $default; + } + + /** + * Check if a string starts with the given string. + * + * @param string $string + * @param string $starts_with + * @return boolean + */ + public static function starts_with($string, $starts_with) + { + return strpos($string, $starts_with) === 0; + } + + /** + * Check if a string ends with the given string. + * + * @param string $string + * @param string $starts_with + * @return boolean + */ + public static function ends_with($string, $ends_with) + { + return substr($string, -strlen($ends_with)) === $ends_with; + } + + /** + * Check if a string contains another string. + * + * @param string $haystack + * @param string $needle + * @return boolean + */ + public static function str_contains($haystack, $needle) + { + return strpos($haystack, $needle) !== false; + } + + /** + * Check if a string contains another string. This version is case + * insensitive. + * + * @param string $haystack + * @param string $needle + * @return boolean + */ + public static function str_icontains($haystack, $needle) + { + return stripos($haystack, $needle) !== false; + } + + /** + * Return the file extension of the given filename. + * + * @param string $filename + * @return string + */ + public static function get_file_ext($filename) + { + return pathinfo($filename, PATHINFO_EXTENSION); + } + + /** + * Removes a directory (and its contents) recursively. + * + * Contributed by Askar (ARACOOL) + * + * @param string $dir The directory to be deleted recursively + * @param bool $traverseSymlinks Delete contents of symlinks recursively + * @return bool + * @throws \RuntimeException + */ + public static function rmdir($dir, $traverseSymlinks = false) + { + if (!file_exists($dir)) { + return true; + } elseif (!is_dir($dir)) { + throw new \RuntimeException('Given path is not a directory'); + } + + if (!is_link($dir) || $traverseSymlinks) { + foreach (scandir($dir) as $file) { + if ($file === '.' || $file === '..') { + continue; + } + + $currentPath = $dir . '/' . $file; + + if (is_dir($currentPath)) { + self::rmdir($currentPath, $traverseSymlinks); + } elseif (!unlink($currentPath)) { + // @codeCoverageIgnoreStart + throw new \RuntimeException('Unable to delete ' . $currentPath); + // @codeCoverageIgnoreEnd + } + } + } + + // Windows treats removing directory symlinks identically to removing directories. + if (is_link($dir) && !defined('PHP_WINDOWS_VERSION_MAJOR')) { + if (!unlink($dir)) { + // @codeCoverageIgnoreStart + throw new \RuntimeException('Unable to delete ' . $dir); + // @codeCoverageIgnoreEnd + } + } else { + if (!rmdir($dir)) { + // @codeCoverageIgnoreStart + throw new \RuntimeException('Unable to delete ' . $dir); + // @codeCoverageIgnoreEnd + } + } + + return true; + } + + /** + * Convert entities, while preserving already-encoded entities. + * + * @param string $string The text to be converted + * @return string + */ + public static function htmlentities($string, $preserve_encoded_entities = false) + { + if ($preserve_encoded_entities) { + // @codeCoverageIgnoreStart + if (defined('HHVM_VERSION')) { + $translation_table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES); + } else { + $translation_table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES, self::mbInternalEncoding()); + } + // @codeCoverageIgnoreEnd + + $translation_table[chr(38)] = '&'; + return preg_replace('/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/', '&', strtr($string, $translation_table)); + } + + return htmlentities($string, ENT_QUOTES, self::mbInternalEncoding()); + } + + /** + * Convert >, <, ', " and & to html entities, but preserves entities that + * are already encoded. + * + * @param string $string The text to be converted + * @return string + */ + public static function htmlspecialchars($string, $preserve_encoded_entities = false) + { + if ($preserve_encoded_entities) { + // @codeCoverageIgnoreStart + if (defined('HHVM_VERSION')) { + $translation_table = get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES); + } else { + $translation_table = get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES, self::mbInternalEncoding()); + } + // @codeCoverageIgnoreEnd + + $translation_table[chr(38)] = '&'; + + return preg_replace('/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/', '&', strtr($string, $translation_table)); + } + + return htmlentities($string, ENT_QUOTES, self::mbInternalEncoding()); + } + + /** + * Transliterates characters to their ASCII equivalents. + * + * Part of the URLify.php Project + * + * @see https://github.com/jbroadway/urlify/blob/master/URLify.php + * + * @param string $text Text that might have not-ASCII characters + * @param string $language Specifies a priority for a specific language. + * @return string Filtered string with replaced "nice" characters + */ + public static function downcode($text, $language = '') + { + self::initLanguageMap($language); + + if (self::seems_utf8($text)) { + if (preg_match_all(self::$regex, $text, $matches)) { + for ($i = 0; $i < count($matches[0]); $i++) { + $char = $matches[0][$i]; + if (isset(self::$map[$char])) { + $text = str_replace($char, self::$map[$char], $text); + } + } + } + } else { + // Not a UTF-8 string so we assume its ISO-8859-1 + $search = "\x80\x83\x8a\x8e\x9a\x9e\x9f\xa2\xa5\xb5\xc0\xc1\xc2\xc3\xc4\xc5\xc7\xc8\xc9\xca\xcb\xcc\xcd"; + $search .= "\xce\xcf\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\xdc\xdd\xe0\xe1\xe2\xe3\xe4\xe5\xe7\xe8\xe9"; + $search .= "\xea\xeb\xec\xed\xee\xef\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xff"; + $text = strtr($text, $search, 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'); + + // These latin characters should be represented by two characters so + // we can't use strtr + $complexSearch = array("\x8c", "\x9c", "\xc6", "\xd0", "\xde", "\xdf", "\xe6", "\xf0", "\xfe"); + $complexReplace = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); + $text = str_replace($complexSearch, $complexReplace, $text); + } + + return $text; + } + + /** + * Converts all accent characters to ASCII characters. + * + * If there are no accent characters, then the string given is just + * returned. + * + * @param string $string Text that might have accent characters + * @param string $language Specifies a priority for a specific language. + * @return string Filtered string with replaced "nice" characters + */ + public static function remove_accents($string, $language = '') + { + if (!preg_match('/[\x80-\xff]/', $string)) { + return $string; + } + + return self::downcode($string, $language); + } + + /** + * Strip all witespaces from the given string. + * + * @param string $string The string to strip + * @return string + */ + public static function strip_space($string) + { + return preg_replace('/\s+/', '', $string); + } + + /** + * Sanitize a string by performing the following operation : + * - Remove accents + * - Lower the string + * - Remove punctuation characters + * - Strip whitespaces + * + * @param string $string the string to sanitize + * @return string + */ + public static function sanitize_string($string) + { + $string = self::remove_accents($string); + $string = strtolower($string); + $string = preg_replace('/[^a-zA-Z 0-9]+/', '', $string); + $string = self::strip_space($string); + + return $string; + } + + /** + * Pads a given string with zeroes on the left. + * + * @param int $number The number to pad + * @param int $length The total length of the desired string + * @return string + */ + public static function zero_pad($number, $length) + { + return str_pad($number, $length, '0', STR_PAD_LEFT); + } + + /** + * Converts a unix timestamp to a relative time string, such as "3 days ago" + * or "2 weeks ago". + * + * @param int $from The date to use as a starting point + * @param int $to The date to compare to, defaults to now + * @param string $suffix The string to add to the end, defaults to " ago" + * @return string + */ + public static function human_time_diff($from, $to = '', $as_text = false, $suffix = ' ago') + { + if ($to == '') { + $to = time(); + } + + $from = new \DateTime(date('Y-m-d H:i:s', $from)); + $to = new \DateTime(date('Y-m-d H:i:s', $to)); + $diff = $from->diff($to); + + if ($diff->y > 1) { + $text = $diff->y . ' years'; + } elseif ($diff->y == 1) { + $text = '1 year'; + } elseif ($diff->m > 1) { + $text = $diff->m . ' months'; + } elseif ($diff->m == 1) { + $text = '1 month'; + } elseif ($diff->d > 7) { + $text = ceil($diff->d / 7) . ' weeks'; + } elseif ($diff->d == 7) { + $text = '1 week'; + } elseif ($diff->d > 1) { + $text = $diff->d . ' days'; + } elseif ($diff->d == 1) { + $text = '1 day'; + } elseif ($diff->h > 1) { + $text = $diff->h . ' hours'; + } elseif ($diff->h == 1) { + $text = ' 1 hour'; + } elseif ($diff->i > 1) { + $text = $diff->i . ' minutes'; + } elseif ($diff->i == 1) { + $text = '1 minute'; + } elseif ($diff->s > 1) { + $text = $diff->s . ' seconds'; + } else { + $text = '1 second'; + } + + if ($as_text) { + $text = explode(' ', $text, 2); + $text = self::number_to_word($text[0]) . ' ' . $text[1]; + } + + return trim($text) . $suffix; + } + + /** + * Converts a number into the text equivalent. For example, 456 becomes four + * hundred and fifty-six. + * + * Part of the IntToWords Project. + * + * @param int|float $number The number to convert into text + * @return string + */ + public static function number_to_word($number) + { + $number = (string) $number; + + if (strpos($number, '.') !== false) { + list($number, $decimal) = explode('.', $number); + } else { + $decimal = false; + } + + $output = ''; + + if ($number[0] == '-') { + $output = 'negative '; + $number = ltrim($number, '-'); + } elseif ($number[0] == '+') { + $output = 'positive '; + $number = ltrim($number, '+'); + } + + if ($number[0] == '0') { + $output .= 'zero'; + } else { + $length = 19; + $number = str_pad($number, 60, '0', STR_PAD_LEFT); + $group = rtrim(chunk_split($number, 3, ' '), ' '); + $groups = explode(' ', $group); + $groups2 = array(); + + foreach ($groups as $group) { + $group[1] = isset($group[1]) ? $group[1] : null; + $group[2] = isset($group[2]) ? $group[2] : null; + $groups2[] = self::numberToWordThreeDigits($group[0], $group[1], $group[2]); + } + + for ($z = 0; $z < count($groups2); $z++) { + if ($groups2[$z] != '') { + $output .= $groups2[$z] . self::numberToWordConvertGroup($length - $z); + $output .= ($z < $length && ! array_search('', array_slice($groups2, $z + 1, -1)) && $groups2[$length] != '' && $groups[$length][0] == '0' ? ' and ' : ', '); + } + } + + $output = rtrim($output, ', '); + } + + if ($decimal > 0) { + $output .= ' point'; + + for ($i = 0; $i < strlen($decimal); $i++) { + $output .= ' ' . self::numberToWordConvertDigit($decimal[$i]); + } + } + + return $output; + } + + protected static function numberToWordConvertGroup($index) + { + switch($index) { + case 11: + return ' decillion'; + case 10: + return ' nonillion'; + case 9: + return ' octillion'; + case 8: + return ' septillion'; + case 7: + return ' sextillion'; + case 6: + return ' quintrillion'; + case 5: + return ' quadrillion'; + case 4: + return ' trillion'; + case 3: + return ' billion'; + case 2: + return ' million'; + case 1: + return ' thousand'; + case 0: + return ''; + } + + return ''; + } + + protected static function numberToWordThreeDigits($digit1, $digit2, $digit3) + { + $output = ''; + + if ($digit1 == '0' && $digit2 == '0' && $digit3 == '0') { + return ''; + } + + if ($digit1 != '0') { + $output .= self::numberToWordConvertDigit($digit1) . ' hundred'; + + if ($digit2 != '0' || $digit3 != '0') { + $output .= ' and '; + } + } + if ($digit2 != '0') { + $output .= self::numberToWordTwoDigits($digit2, $digit3); + } elseif ($digit3 != '0') { + $output .= self::numberToWordConvertDigit($digit3); + } + + return $output; + } + + protected static function numberToWordTwoDigits($digit1, $digit2) + { + if ($digit2 == '0') { + switch ($digit1) { + case '1': + return 'ten'; + case '2': + return 'twenty'; + case '3': + return 'thirty'; + case '4': + return 'forty'; + case '5': + return 'fifty'; + case '6': + return 'sixty'; + case '7': + return 'seventy'; + case '8': + return 'eighty'; + case '9': + return 'ninety'; + } + } elseif ($digit1 == '1') { + switch ($digit2) { + case '1': + return 'eleven'; + case '2': + return 'twelve'; + case '3': + return 'thirteen'; + case '4': + return 'fourteen'; + case '5': + return 'fifteen'; + case '6': + return 'sixteen'; + case '7': + return 'seventeen'; + case '8': + return 'eighteen'; + case '9': + return 'nineteen'; + } + } else { + $second_digit = self::numberToWordConvertDigit($digit2); + + switch ($digit1) { + case '2': + return "twenty-{$second_digit}"; + case '3': + return "thirty-{$second_digit}"; + case '4': + return "forty-{$second_digit}"; + case '5': + return "fifty-{$second_digit}"; + case '6': + return "sixty-{$second_digit}"; + case '7': + return "seventy-{$second_digit}"; + case '8': + return "eighty-{$second_digit}"; + case '9': + return "ninety-{$second_digit}"; + } + } + } + + /** + * @param $digit + * @return string + * @throws \LogicException + */ + protected static function numberToWordConvertDigit($digit) + { + switch ($digit) { + case '0': + return 'zero'; + case '1': + return 'one'; + case '2': + return 'two'; + case '3': + return 'three'; + case '4': + return 'four'; + case '5': + return 'five'; + case '6': + return 'six'; + case '7': + return 'seven'; + case '8': + return 'eight'; + case '9': + return 'nine'; + default: + throw new \LogicException('Not a number'); + } + } + + /** + * Transmit UTF-8 content headers if the headers haven't already been sent. + * + * @param string $content_type The content type to send out + * @return boolean + */ + public static function utf8_headers($content_type = 'text/html') + { + // @codeCoverageIgnoreStart + if (!headers_sent()) { + header('Content-type: ' . $content_type . '; charset=utf-8'); + + return true; + } + + return false; + // @codeCoverageIgnoreEnd + } + + /** + * Transmit headers that force a browser to display the download file + * dialog. Cross browser compatible. Only fires if headers have not + * already been sent. + * + * @param string $filename The name of the filename to display to + * browsers + * @param string $content The content to output for the download. + * If you don't specify this, just the + * headers will be sent + * @return boolean + */ + public static function force_download($filename, $content = false) + { + // @codeCoverageIgnoreStart + if (!headers_sent()) { + // Required for some browsers + if (ini_get('zlib.output_compression')) { + @ini_set('zlib.output_compression', 'Off'); + } + + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + + // Required for certain browsers + header('Cache-Control: private', false); + + header('Content-Disposition: attachment; filename="' . basename(str_replace('"', '', $filename)) . '";'); + header('Content-Type: application/force-download'); + header('Content-Transfer-Encoding: binary'); + + if ($content) { + header('Content-Length: ' . strlen($content)); + } + + ob_clean(); + flush(); + + if ($content) { + echo $content; + } + + return true; + } + + return false; + // @codeCoverageIgnoreEnd + } + + /** + * Sets the headers to prevent caching for the different browsers. + * + * Different browsers support different nocache headers, so several + * headers must be sent so that all of them get the point that no + * caching should occur + * + * @return boolean + */ + public static function nocache_headers() + { + // @codeCoverageIgnoreStart + if (!headers_sent()) { + header('Expires: Wed, 11 Jan 1984 05:00:00 GMT'); + header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); + header('Cache-Control: no-cache, must-revalidate, max-age=0'); + header('Pragma: no-cache'); + + return true; + } + + return false; + // @codeCoverageIgnoreEnd + } + + /** + * Generates a string of random characters. + * + * @throws LengthException If $length is bigger than the available + * character pool and $no_duplicate_chars is + * enabled + * + * @param integer $length The length of the string to + * generate + * @param boolean $human_friendly Whether or not to make the + * string human friendly by + * removing characters that can be + * confused with other characters ( + * O and 0, l and 1, etc) + * @param boolean $include_symbols Whether or not to include + * symbols in the string. Can not + * be enabled if $human_friendly is + * true + * @param boolean $no_duplicate_chars Whether or not to only use + * characters once in the string. + * @return string + */ + public static function random_string($length = 16, $human_friendly = true, $include_symbols = false, $no_duplicate_chars = false) + { + $nice_chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefhjkmnprstuvwxyz23456789'; + $all_an = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'; + $symbols = '!@#$%^&*()~_-=+{}[]|:;<>,.?/"\'\\`'; + $string = ''; + + // Determine the pool of available characters based on the given parameters + if ($human_friendly) { + $pool = $nice_chars; + } else { + $pool = $all_an; + + if ($include_symbols) { + $pool .= $symbols; + } + } + + if (!$no_duplicate_chars) { + return substr(str_shuffle(str_repeat($pool, $length)), 0, $length); + } + + // Don't allow duplicate letters to be disabled if the length is + // longer than the available characters + if ($no_duplicate_chars && strlen($pool) < $length) { + throw new \LengthException('$length exceeds the size of the pool and $no_duplicate_chars is enabled'); + } + + // Convert the pool of characters into an array of characters and + // shuffle the array + $pool = str_split($pool); + $poolLength = count($pool); + $rand = mt_rand(0, $poolLength - 1); + + // Generate our string + for ($i = 0; $i < $length; $i++) { + $string .= $pool[$rand]; + + // Remove the character from the array to avoid duplicates + array_splice($pool, $rand, 1); + + // Generate a new number + if (($poolLength - 2 - $i) > 0) { + $rand = mt_rand(0, $poolLength - 2 - $i); + } else { + $rand = 0; + } + } + + return $string; + } + + /** + * Generate secure random string of given length + * If 'openssl_random_pseudo_bytes' is not available + * then generate random string using default function + * + * Part of the Laravel Project + * + * @param int $length length of string + * @return bool + */ + public static function secure_random_string($length = 16) + { + if (function_exists('openssl_random_pseudo_bytes')) { + $bytes = openssl_random_pseudo_bytes($length * 2); + + if ($bytes === false) { + throw new \LengthException('$length is not accurate, unable to generate random string'); + } + + return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length); + } + + // @codeCoverageIgnoreStart + return static::random_string($length); + // @codeCoverageIgnoreEnd + } + + /** + * Check if a given string matches a given pattern. + * + * Contributed by Abhimanyu Sharma + * + * @param string $pattern Parttern of string exptected + * @param string $string String that need to be matched + * @return bool + */ + public static function match_string($pattern, $string, $caseSensitive = true) + { + if ($pattern == $string) { + return true; + } + + // Preg flags + $flags = $caseSensitive ? '' : 'i'; + + // Escape any regex special characters + $pattern = preg_quote($pattern, '#'); + + // Unescape * which is our wildcard character and change it to .* + $pattern = str_replace('\*', '.*', $pattern); + + return (bool) preg_match('#^' . $pattern . '$#' . $flags, $string); + } + + /** + * Validate an email address. + * + * @param string $possible_email An email address to validate + * @return bool + */ + public static function validate_email($possible_email) + { + return (bool) filter_var($possible_email, FILTER_VALIDATE_EMAIL); + } + + /** + * Return the URL to a user's gravatar. + * + * @param string $email The email of the user + * @param integer $size The size of the gravatar + * @return string + */ + public static function get_gravatar($email, $size = 32) + { + if (self::is_https()) { + $url = 'https://secure.gravatar.com/'; + } else { + $url = 'http://www.gravatar.com/'; + } + + $url .= 'avatar/' . md5($email) . '?s=' . (int) abs($size); + + return $url; + } + + /** + * Turns all of the links in a string into HTML links. + * + * Part of the LinkifyURL Project + * + * @param string $text The string to parse + * @return string + */ + public static function linkify($text) + { + $text = preg_replace('/'/', ''', $text); // IE does not handle ' entity! + $section_html_pattern = '%# Rev:20100913_0900 github.com/jmrware/LinkifyURL + # Section text into HTML tags and everything else. + ( # $1: Everything not HTML tag. + [^<]+(?:(?!... tag. + ]*> # opening tag. + [^<]*(?:(?! # closing tag. + ) # End $2: + %ix'; + + return preg_replace_callback($section_html_pattern, array(__CLASS__, 'linkifyCallback'), $text); + } + + /** + * Callback for the preg_replace in the linkify() method. + * + * Part of the LinkifyURL Project + * + * @param array $matches Matches from the preg_ function + * @return string + */ + protected static function linkifyRegex($text) + { + $url_pattern = '/# Rev:20100913_0900 github.com\/jmrware\/LinkifyURL + # Match http & ftp URL that is not already linkified. + # Alternative 1: URL delimited by (parentheses). + (\() # $1 "(" start delimiter. + ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $2: URL. + (\)) # $3: ")" end delimiter. + | # Alternative 2: URL delimited by [square brackets]. + (\[) # $4: "[" start delimiter. + ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $5: URL. + (\]) # $6: "]" end delimiter. + | # Alternative 3: URL delimited by {curly braces}. + (\{) # $7: "{" start delimiter. + ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $8: URL. + (\}) # $9: "}" end delimiter. + | # Alternative 4: URL delimited by . + (<|&(?:lt|\#60|\#x3c);) # $10: "<" start delimiter (or HTML entity). + ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $11: URL. + (>|&(?:gt|\#62|\#x3e);) # $12: ">" end delimiter (or HTML entity). + | # Alternative 5: URL not delimited by (), [], {} or <>. + (# $13: Prefix proving URL not already linked. + (?: ^ # Can be a beginning of line or string, or + | [^=\s\'"\]] # a non-"=", non-quote, non-"]", followed by + ) \s*[\'"]? # optional whitespace and optional quote; + | [^=\s]\s+ # or... a non-equals sign followed by whitespace. + ) # End $13. Non-prelinkified-proof prefix. + (\b # $14: Other non-delimited URL. + (?:ht|f)tps?:\/\/ # Required literal http, https, ftp or ftps prefix. + [a-z0-9\-._~!$\'()*+,;=:\/?#[\]@%]+ # All URI chars except "&" (normal*). + (?: # Either on a "&" or at the end of URI. + (?! # Allow a "&" char only if not start of an... + &(?:gt|\#0*62|\#x0*3e); # HTML ">" entity, or + | &(?:amp|apos|quot|\#0*3[49]|\#x0*2[27]); # a [&\'"] entity if + [.!&\',:?;]? # followed by optional punctuation then + (?:[^a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]|$) # a non-URI char or EOS. + ) & # If neg-assertion true, match "&" (special). + [a-z0-9\-._~!$\'()*+,;=:\/?#[\]@%]* # More non-& URI chars (normal*). + )* # Unroll-the-loop (special normal*)*. + [a-z0-9\-_~$()*+=\/#[\]@%] # Last char can\'t be [.!&\',;:?] + ) # End $14. Other non-delimited URL. + /imx'; + + $url_replace = '$1$4$7$10$13$2$5$8$11$14$3$6$9$12'; + + return preg_replace($url_pattern, $url_replace, $text); + } + + /** + * Callback for the preg_replace in the linkify() method. + * + * Part of the LinkifyURL Project + * + * @param array $matches Matches from the preg_ function + * @return string + */ + protected static function linkifyCallback($matches) + { + if (isset($matches[2])) { + return $matches[2]; + } + + return self::linkifyRegex($matches[1]); + } + + /** + * Return the current URL. + * + * @return string + */ + public static function get_current_url() + { + $url = ''; + + // Check to see if it's over https + $is_https = self::is_https(); + if ($is_https) { + $url .= 'https://'; + } else { + $url .= 'http://'; + } + + // Was a username or password passed? + if (isset($_SERVER['PHP_AUTH_USER'])) { + $url .= $_SERVER['PHP_AUTH_USER']; + + if (isset($_SERVER['PHP_AUTH_PW'])) { + $url .= ':' . $_SERVER['PHP_AUTH_PW']; + } + + $url .= '@'; + } + + + // We want the user to stay on the same host they are currently on, + // but beware of security issues + // see http://shiflett.org/blog/2006/mar/server-name-versus-http-host + $url .= $_SERVER['HTTP_HOST']; + + $port = $_SERVER['SERVER_PORT']; + + // Is it on a non standard port? + if ($is_https && ($port != 443)) { + $url .= ':' . $_SERVER['SERVER_PORT']; + } elseif (!$is_https && ($port != 80)) { + $url .= ':' . $_SERVER['SERVER_PORT']; + } + + // Get the rest of the URL + if (!isset($_SERVER['REQUEST_URI'])) { + // Microsoft IIS doesn't set REQUEST_URI by default + $url .= $_SERVER['PHP_SELF']; + + if (isset($_SERVER['QUERY_STRING'])) { + $url .= '?' . $_SERVER['QUERY_STRING']; + } + } else { + $url .= $_SERVER['REQUEST_URI']; + } + + return $url; + } + + /** + * Returns the IP address of the client. + * + * @param boolean $trust_proxy_headers Whether or not to trust the + * proxy headers HTTP_CLIENT_IP + * and HTTP_X_FORWARDED_FOR. ONLY + * use if your server is behind a + * proxy that sets these values + * @return string + */ + public static function get_client_ip($trust_proxy_headers = false) + { + if (!$trust_proxy_headers) { + return $_SERVER['REMOTE_ADDR']; + } + + if (!empty($_SERVER['HTTP_CLIENT_IP'])) { + $ip = $_SERVER['HTTP_CLIENT_IP']; + } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else { + $ip = $_SERVER['REMOTE_ADDR']; + } + + return $ip; + } + + /** + * Truncate a string to a specified length without cutting a word off. + * + * @param string $string The string to truncate + * @param integer $length The length to truncate the string to + * @param string $append Text to append to the string IF it gets + * truncated, defaults to '...' + * @return string + */ + public static function safe_truncate($string, $length, $append = '...') + { + $ret = substr($string, 0, $length); + $last_space = strrpos($ret, ' '); + + if ($last_space !== false && $string != $ret) { + $ret = substr($ret, 0, $last_space); + } + + if ($ret != $string) { + $ret .= $append; + } + + return $ret; + } + + + /** + * Truncate the string to given length of charactes. + * + * @param $string + * @param $limit + * @param string $append + * @return string + */ + public static function limit_characters($string, $limit = 100, $append = '...') + { + if (mb_strlen($string) <= $limit) { + return $string; + } + + return rtrim(mb_substr($string, 0, $limit, 'UTF-8')) . $append; + } + + /** + * Truncate the string to given length of words. + * + * @param $string + * @param $limit + * @param string $append + * @return string + */ + public static function limit_words($string, $limit = 100, $append = '...') + { + preg_match('/^\s*+(?:\S++\s*+){1,' . $limit . '}/u', $string, $matches); + + if (!isset($matches[0]) || strlen($string) === strlen($matches[0])) { + return $string; + } + + return rtrim($matches[0]).$append; + } + + /** + * Returns the ordinal version of a number (appends th, st, nd, rd). + * + * @param string $number The number to append an ordinal suffix to + * @return string + */ + public static function ordinal($number) + { + $test_c = abs($number) % 10; + $ext = ((abs($number) % 100 < 21 && abs($number) % 100 > 4) ? 'th' : (($test_c < 4) ? ($test_c < 3) ? ($test_c < 2) ? ($test_c < 1) ? 'th' : 'st' : 'nd' : 'rd' : 'th')); + + return $number . $ext; + } + + /** + * Returns the file permissions as a nice string, like -rw-r--r-- or false + * if the file is not found. + * + * @param string $file The name of the file to get permissions form + * @param int $perms Numerical value of permissions to display as text. + * @return string + */ + public static function full_permissions($file, $perms = null) + { + if (is_null($perms)) { + if (!file_exists($file)) { + return false; + } + $perms = fileperms($file); + } + + if (($perms & 0xC000) == 0xC000) { + // Socket + $info = 's'; + } elseif (($perms & 0xA000) == 0xA000) { + // Symbolic Link + $info = 'l'; + } elseif (($perms & 0x8000) == 0x8000) { + // Regular + $info = '-'; + } elseif (($perms & 0x6000) == 0x6000) { + // Block special + $info = 'b'; + } elseif (($perms & 0x4000) == 0x4000) { + // Directory + $info = 'd'; + } elseif (($perms & 0x2000) == 0x2000) { + // Character special + $info = 'c'; + } elseif (($perms & 0x1000) == 0x1000) { + // FIFO pipe + $info = 'p'; + } else { + // Unknown + $info = 'u'; + } + + // Owner + $info .= (($perms & 0x0100) ? 'r' : '-'); + $info .= (($perms & 0x0080) ? 'w' : '-'); + $info .= (($perms & 0x0040) ? + (($perms & 0x0800) ? 's' : 'x') : + (($perms & 0x0800) ? 'S' : '-')); + + // Group + $info .= (($perms & 0x0020) ? 'r' : '-'); + $info .= (($perms & 0x0010) ? 'w' : '-'); + $info .= (($perms & 0x0008) ? + (($perms & 0x0400) ? 's' : 'x') : + (($perms & 0x0400) ? 'S' : '-')); + + // World + $info .= (($perms & 0x0004) ? 'r' : '-'); + $info .= (($perms & 0x0002) ? 'w' : '-'); + $info .= (($perms & 0x0001) ? + (($perms & 0x0200) ? 't' : 'x') : + (($perms & 0x0200) ? 'T' : '-')); + + return $info; + } + + /** + * Returns the first element in an array. + * + * @param array $array + * @return mixed + */ + public static function array_first(array $array) + { + return reset($array); + } + + /** + * Returns the last element in an array. + * + * @param array $array + * @return mixed + */ + public static function array_last(array $array) + { + return end($array); + } + + /** + * Returns the first key in an array. + * + * @param array $array + * @return int|string + */ + public static function array_first_key(array $array) + { + reset($array); + + return key($array); + } + + /** + * Returns the last key in an array. + * + * @param array $array + * @return int|string + */ + public static function array_last_key(array $array) + { + end($array); + + return key($array); + } + + /** + * Flatten a multi-dimensional array into a one dimensional array. + * + * Contributed by Theodore R. Smith of PHP Experts, Inc. + * + * @param array $array The array to flatten + * @param boolean $preserve_keys Whether or not to preserve array keys. + * Keys from deeply nested arrays will + * overwrite keys from shallowy nested arrays + * @return array + */ + public static function array_flatten(array $array, $preserve_keys = true) + { + $flattened = array(); + + array_walk_recursive($array, function($value, $key) use (&$flattened, $preserve_keys) { + if ($preserve_keys && !is_int($key)) { + $flattened[$key] = $value; + } else { + $flattened[] = $value; + } + }); + + return $flattened; + } + + /** + * Accepts an array, and returns an array of values from that array as + * specified by $field. For example, if the array is full of objects + * and you call util::array_pluck($array, 'name'), the function will + * return an array of values from $array[]->name. + * + * @param array $array An array + * @param string $field The field to get values from + * @param boolean $preserve_keys Whether or not to preserve the + * array keys + * @param boolean $remove_nomatches If the field doesn't appear to be set, + * remove it from the array + * @return array + */ + public static function array_pluck(array $array, $field, $preserve_keys = true, $remove_nomatches = true) + { + $new_list = array(); + + foreach ($array as $key => $value) { + if (is_object($value)) { + if (isset($value->{$field})) { + if ($preserve_keys) { + $new_list[$key] = $value->{$field}; + } else { + $new_list[] = $value->{$field}; + } + } elseif (!$remove_nomatches) { + $new_list[$key] = $value; + } + } else { + if (isset($value[$field])) { + if ($preserve_keys) { + $new_list[$key] = $value[$field]; + } else { + $new_list[] = $value[$field]; + } + } elseif (!$remove_nomatches) { + $new_list[$key] = $value; + } + } + } + + return $new_list; + } + + /** + * Searches for a given value in an array of arrays, objects and scalar + * values. You can optionally specify a field of the nested arrays and + * objects to search in. + * + * @param array $array The array to search + * @param scalar $search The value to search for + * @param string $field The field to search in, if not specified + * all fields will be searched + * @return boolean|scalar False on failure or the array key on success + */ + public static function array_search_deep(array $array, $search, $field = false) + { + // *grumbles* stupid PHP type system + $search = (string) $search; + + foreach ($array as $key => $elem) { + // *grumbles* stupid PHP type system + $key = (string) $key; + + if ($field) { + if (is_object($elem) && $elem->{$field} === $search) { + return $key; + } elseif (is_array($elem) && $elem[$field] === $search) { + return $key; + } elseif (is_scalar($elem) && $elem === $search) { + return $key; + } + } else { + if (is_object($elem)) { + $elem = (array) $elem; + + if (in_array($search, $elem)) { + return $key; + } + } elseif (is_array($elem) && in_array($search, $elem)) { + return $key; + } elseif (is_scalar($elem) && $elem === $search) { + return $key; + } + } + } + + return false; + } + + /** + * Returns an array containing all the elements of arr1 after applying + * the callback function to each one. + * + * @param string $callback Callback function to run for each + * element in each array + * @param array $array An array to run through the callback + * function + * @param boolean $on_nonscalar Whether or not to call the callback + * function on nonscalar values + * (Objects, resources, etc) + * @return array + */ + public static function array_map_deep(array $array, $callback, $on_nonscalar = false) + { + foreach ($array as $key => $value) { + if (is_array($value)) { + $args = array($value, $callback, $on_nonscalar); + $array[$key] = call_user_func_array(array(__CLASS__, __FUNCTION__), $args); + } elseif (is_scalar($value) || $on_nonscalar) { + $array[$key] = call_user_func($callback, $value); + } + } + + return $array; + } + + public static function array_clean(array $array) + { + return array_filter($array); + } + + /** + * Wrapper to prevent errors if the user doesn't have the mbstring + * extension installed. + * + * @param string $encoding + * @return string + */ + protected static function mbInternalEncoding($encoding = null) + { + if (function_exists('mb_internal_encoding')) { + return $encoding ? mb_internal_encoding($encoding) : mb_internal_encoding(); + } + + // @codeCoverageIgnoreStart + return 'UTF-8'; + // @codeCoverageIgnoreEnd + } + + /** + * Set the writable bit on a file to the minimum value that allows the user + * running PHP to write to it. + * + * @param string $filename The filename to set the writable bit on + * @param boolean $writable Whether to make the file writable or not + * @return boolean + */ + public static function set_writable($filename, $writable = true) + { + $stat = @stat($filename); + + if ($stat === false) { + return false; + } + + // We're on Windows + if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { + return true; + } + + list($myuid, $mygid) = array(posix_geteuid(), posix_getgid()); + + if ($writable) { + // Set only the user writable bit (file is owned by us) + if ($stat['uid'] == $myuid) { + return chmod($filename, fileperms($filename) | 0200); + } + + // Set only the group writable bit (file group is the same as us) + if ($stat['gid'] == $mygid) { + return chmod($filename, fileperms($filename) | 0220); + } + + // Set the world writable bit (file isn't owned or grouped by us) + return chmod($filename, fileperms($filename) | 0222); + } else { + // Set only the user writable bit (file is owned by us) + if ($stat['uid'] == $myuid) { + return chmod($filename, (fileperms($filename) | 0222) ^ 0222); + } + + // Set only the group writable bit (file group is the same as us) + if ($stat['gid'] == $mygid) { + return chmod($filename, (fileperms($filename) | 0222) ^ 0022); + } + + // Set the world writable bit (file isn't owned or grouped by us) + return chmod($filename, (fileperms($filename) | 0222) ^ 0002); + } + } + + /** + * Set the readable bit on a file to the minimum value that allows the user + * running PHP to read to it. + * + * @param string $filename The filename to set the readable bit on + * @param boolean $readable Whether to make the file readable or not + * @return boolean + */ + public static function set_readable($filename, $readable = true) + { + $stat = @stat($filename); + + if ($stat === false) { + return false; + } + + // We're on Windows + if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { + return true; + } + + list($myuid, $mygid) = array(posix_geteuid(), posix_getgid()); + + if ($readable) { + // Set only the user readable bit (file is owned by us) + if ($stat['uid'] == $myuid) { + return chmod($filename, fileperms($filename) | 0400); + } + + // Set only the group readable bit (file group is the same as us) + if ($stat['gid'] == $mygid) { + return chmod($filename, fileperms($filename) | 0440); + } + + // Set the world readable bit (file isn't owned or grouped by us) + return chmod($filename, fileperms($filename) | 0444); + } else { + // Set only the user readable bit (file is owned by us) + if ($stat['uid'] == $myuid) { + return chmod($filename, (fileperms($filename) | 0444) ^ 0444); + } + + // Set only the group readable bit (file group is the same as us) + if ($stat['gid'] == $mygid) { + return chmod($filename, (fileperms($filename) | 0444) ^ 0044); + } + + // Set the world readable bit (file isn't owned or grouped by us) + return chmod($filename, (fileperms($filename) | 0444) ^ 0004); + } + } + + /** + * Set the executable bit on a file to the minimum value that allows the + * user running PHP to read to it. + * + * @param string $filename The filename to set the executable bit on + * @param boolean $executable Whether to make the file executable or not + * @return boolean + */ + public static function set_executable($filename, $executable = true) + { + $stat = @stat($filename); + + if ($stat === false) { + return false; + } + + // We're on Windows + if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { + return true; + } + + list($myuid, $mygid) = array(posix_geteuid(), posix_getgid()); + + if ($executable) { + // Set only the user readable bit (file is owned by us) + if ($stat['uid'] == $myuid) { + return chmod($filename, fileperms($filename) | 0100); + } + + // Set only the group readable bit (file group is the same as us) + if ($stat['gid'] == $mygid) { + return chmod($filename, fileperms($filename) | 0110); + } + + // Set the world readable bit (file isn't owned or grouped by us) + return chmod($filename, fileperms($filename) | 0111); + } else { + // Set only the user readable bit (file is owned by us) + if ($stat['uid'] == $myuid) { + return chmod($filename, (fileperms($filename) | 0111) ^ 0111); + } + + // Set only the group readable bit (file group is the same as us) + if ($stat['gid'] == $mygid) { + return chmod($filename, (fileperms($filename) | 0111) ^ 0011); + } + + // Set the world readable bit (file isn't owned or grouped by us) + return chmod($filename, (fileperms($filename) | 0111) ^ 0001); + } + } + + /** + * Returns size of a given directory in bytes. + * + * @param string $dir + * @return integer + */ + public static function directory_size($dir) + { + $size = 0; + foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS)) as $file => $key) { + if ($key->isFile()) { + $size += $key->getSize(); + } + } + return $size; + } + + /** + * Returns a home directory of current user. + * + * @return string + */ + public static function get_user_directory() + { + if (isset($_SERVER['HOMEDRIVE'])) return $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH']; + else return $_SERVER['HOME']; + } + + /** + * Returns all paths inside a directory. + * + * @param string $dir + * @return array + */ + public static function directory_contents($dir) + { + $contents = array(); + foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS)) as $pathname => $fi) { + $contents[] = $pathname; + } + natsort($contents); + return $contents; + } +} diff --git a/e_lib/util.php b/e_lib/util.php new file mode 100644 index 00000000..1b209796 --- /dev/null +++ b/e_lib/util.php @@ -0,0 +1,10 @@ + + */ +class util extends \utilphp\util { } diff --git a/e_lib/utilphp-1.1.0/.coveralls.yml b/e_lib/utilphp-1.1.0/.coveralls.yml new file mode 100644 index 00000000..6e649991 --- /dev/null +++ b/e_lib/utilphp-1.1.0/.coveralls.yml @@ -0,0 +1 @@ +service_name: travis-ci \ No newline at end of file diff --git a/e_lib/utilphp-1.1.0/.gitignore b/e_lib/utilphp-1.1.0/.gitignore new file mode 100644 index 00000000..a28cc36f --- /dev/null +++ b/e_lib/utilphp-1.1.0/.gitignore @@ -0,0 +1,4 @@ +test.php +build/* +report/* +tests/test* diff --git a/e_lib/utilphp-1.1.0/.travis.yml b/e_lib/utilphp-1.1.0/.travis.yml new file mode 100644 index 00000000..bfce66e7 --- /dev/null +++ b/e_lib/utilphp-1.1.0/.travis.yml @@ -0,0 +1,22 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +matrix: + allow_failures: + - php: hhvm + +before_script: + - pyrus install pear/PHP_CodeSniffer + - wget -nc http://getcomposer.org/composer.phar + - php composer.phar install --dev --no-interaction + - mkdir -p build/logs + - phpenv rehash + +after_script: + - php vendor/bin/coveralls diff --git a/e_lib/utilphp-1.1.0/CHANGELOG.md b/e_lib/utilphp-1.1.0/CHANGELOG.md new file mode 100644 index 00000000..8cbd899f --- /dev/null +++ b/e_lib/utilphp-1.1.0/CHANGELOG.md @@ -0,0 +1,86 @@ +Change Log +========== + +1.1.0 +----- + +This release introduces a deprecation notice for `slugify()`, please update your code. + +* Added a cryptographically secure random string function `secure_random_string`. Thanks to @abhimanyusharma003 via [Pull Request #53](https://github.com/brandonwamboldt/utilphp/pull/53) +* Added `limit_characters` and `limit_words` functions. Thanks to @abhimanyusharma003 via [Pull Request #55](https://github.com/brandonwamboldt/utilphp/pull/55) +* Added `rmdir` method to recursively delete a directory. Thanks to @ARACOOOL via [Pull Request #56](https://github.com/brandonwamboldt/utilphp/pull/56) +* Added `set_executable`, `set_readable`, `set_writable`, `directory_size`, `directory_contents` and `get_user_dir` functions. Thanks to @sergserg via [Pull Request #70](https://github.com/brandonwamboldt/utilphp/pull/70) +* Changed parameter ordering for `slugify`, `$css_mode` is now the third argument. For backwards compatibility, the old order will still work but it will generate an `E_USER_DEPRECATED` warning. Thanks to @abhimanyusharma003 via [Pull Request #71](https://github.com/brandonwamboldt/utilphp/pull/71) +* Added `match_string` method. Thanks to @abhimanyusharma003 via [Pull Request #72](https://github.com/brandonwamboldt/utilphp/pull/72) +* Renamed internal methods (protected ones) for PSR-2 compliance +* General performance improvements, code quality improvements, and increased unit test coverage (special thanks to @hopeseekr for getting us near 100% coverage) + +1.0.7 +----- + +* Added `fix_broken_serialization` to fix broken serialized strings (Thanks to @hopeseekr via [Pull Request #48](https://github.com/brandonwamboldt/utilphp/pull/48)) +* Fixed `get_current_url` appending port 80 or 443 when not needed (Thanks to @scottchiefbaker via [Pull Request #49](https://github.com/brandonwamboldt/utilphp/pull/49)) +* `var_dump` can now handle recursive data structures without crashing +* `var_dump` code was minified and cleaned up +* `array_flatten` was optimized (thanks to @hopeseekr via [Pull Request #47](https://github.com/brandonwamboldt/utilphp/pull/47)) +* `remove_accents` was completely rewritten and is now ~4x faster + +1.0.6 +----- + +* Added `start_with` function +* Added `ends_with` function +* Added `str_contains` function +* Added `str_icontains` function +* Added `get_file_ext` function +* Fixing permissions on the files & directories +* Fixing a bug with the include path of util.php + +1.0.5 +----- + +* [Issue #29](https://github.com/brandonwamboldt/utilphp/issues/29) Fixed error in `var_dump` if mbstring extension wasn't present +* Adding Composer support +* Updating license from GPL to MIT +* Adding Changelog to project +* Bumping minimum version to PHP 5.3.3 + +1.0.4 +----- + +* [Issue #22](https://github.com/brandonwamboldt/utilphp/issues/22) Removed all superglobal *_get functions, you can use the modified array_get now +* [Issue #22](https://github.com/brandonwamboldt/utilphp/issues/22) Modifed the behaviour of `array_get`, see documentation +* [Pull Request #21](https://github.com/brandonwamboldt/utilphp/pull/21) Added multibyte support to html* functions +* [Issue #9](https://github.com/brandonwamboldt/utilphp/issues/9) Removed the `str_to_utf8` function +* [Issue #3](https://github.com/brandonwamboldt/utilphp/issues/3) Removed the `absint` function +* Removed declare() from util.php to avoid errors +* Updated PHPUnit tests to use PHPUnit 3.6 + +1.0.3 +----- + +* [Issue #16](https://github.com/brandonwamboldt/utilphp/issues/16) Improved performance of `slugify` +* [Issue #14](https://github.com/brandonwamboldt/utilphp/issues/14) Modified the regex for `seems_utf8` to be more accurate +* [Issue #13](https://github.com/brandonwamboldt/utilphp/issues/13) Changed `validate_email` to be wrapper for `filter_var` +* Added 'ok' to the list of yes words for `str_to_bool` +* `str_to_bool` matches no followed by any number of 'o's + +1.0.2 +----- + +* [Issue #12](https://github.com/brandonwamboldt/utilphp/issues/12) `get_current_url` now includes the port and user/password if required +* [Issue #11](https://github.com/brandonwamboldt/utilphp/issues/11) `human_time_diff` now uses the DateTime functions +* [Issue #10](https://github.com/brandonwamboldt/utilphp/issues/10) `is_https` no longer checks the port as well + +1.0.1 +----- + +* [Issue #7](https://github.com/brandonwamboldt/utilphp/issues/7) Added the `$trust_proxy_headers` parameter to `get_client_ip` +* [Issue #6](https://github.com/brandonwamboldt/utilphp/issues/6) Removed `is_isset` as the function did not work as intended +* [Issue #6](https://github.com/brandonwamboldt/utilphp/issues/6) Removed `is_empty` as it is redundant, use ! with function calls instead +* Fixed a bug with `get_gravatar` + +1.0.0 +----- + +* Initial release of util.php. diff --git a/e_lib/utilphp-1.1.0/CONTRIBUTORS.md b/e_lib/utilphp-1.1.0/CONTRIBUTORS.md new file mode 100644 index 00000000..7fadf04f --- /dev/null +++ b/e_lib/utilphp-1.1.0/CONTRIBUTORS.md @@ -0,0 +1,48 @@ +# CONTRIBUTORS + +Util.php is the combined effort of many people who contributed new functions and features, bug fixes, tests, and documentation. + +# Maintainer / Lead + +* Brandon Wamboldt (http://brandonwamboldt.ca) + +## Third-Party Projects + +The following projects were fully or partially incorporated into util.php (and properly attributed). + +* IntToWords (https://github.com/hemant347/IntToWords) +* LinkifyURL (https://github.com/jmrware/LinkifyURL) +* URLify.php (https://github.com/jbroadway/urlify/) +* Pure PHP http_build_url (https://github.com/jakeasmith/http_build_url) + +## Methods + +The following developers and/or companies helped contribute to building util.php. + +* PHP Experts, Inc. (http://www.phpexperts.pro/) + - `array_flatten()` + - `fix_broken_serialization()` + - Lots of unit tests. +* Tony Ferrara (ircmaxwell, http://blog.ircmaxell.com/) + - `seemsUtf8Regex()`: http://stackoverflow.com/a/11709412/430062 +* Askar ([@ARACOOOL](https://github.com/ARACOOOL)) + - `rmdir()` + - `limit_characters()` + - `limit_words()` +* Anonymous (tmp1000@fastmail.fm) + - `htmlspecialentities()`: http://php.timesoft.cc/manual/en/function.htmlentities.php + - `htmlspecialchars()` +* Laravel Project (https://github.com/laravel/laravel) + - `secure_random_string()`: http://trac.allenjb.me.uk/php/browser/tagi/vendor/laravel/framework/src/Illuminate/Support/Str.php?rev=87#L127 +* Abhimanyu Sharma ([@abhimanyusharma003](https://github.com/abhimanyusharma003)) + - `limit_characters()` + - `limit_words()` + - `match_string()` +* Scott Baker ([@scottchiefbaker](https://github.com/scottchiefbaker)) +* [@sergserg](https://github.com/sergserg) + - `set_writable()` + - `set_executable()` + - `set_readable()` + - `directory_size()` + - `directory_contents()` + - `get_user_dir()` diff --git a/e_lib/utilphp-1.1.0/LICENSE.md b/e_lib/utilphp-1.1.0/LICENSE.md new file mode 100644 index 00000000..7c3f2915 --- /dev/null +++ b/e_lib/utilphp-1.1.0/LICENSE.md @@ -0,0 +1,24 @@ +The MIT License (MIT) +===================== + +The MIT License (MIT) + +Copyright (c) 2013 Brandon Wamboldt + +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. \ No newline at end of file diff --git a/e_lib/utilphp-1.1.0/README.md b/e_lib/utilphp-1.1.0/README.md new file mode 100644 index 00000000..3b271796 --- /dev/null +++ b/e_lib/utilphp-1.1.0/README.md @@ -0,0 +1,123 @@ +# Util.php [![Build Status](https://img.shields.io/travis/brandonwamboldt/utilphp.svg)](https://travis-ci.org/brandonwamboldt/utilphp) [![Coverage Status](https://img.shields.io/coveralls/brandonwamboldt/utilphp/master.svg)](https://coveralls.io/r/brandonwamboldt/utilphp) + +[UtilPHP](http://brandonwamboldt.github.com/utilphp/) (Aka util.php) is a +collection of useful functions and snippets that you need or could use every +day. It's implemented as a class with static methods, to avoid conflicts with +your existing code-base. Just drop it in and start using it immediately. + +Included are 55+ functions that provide you with the ability to do common +tasks much easier and more efficiently, without having to find that one comment +on php.net where you know it's been done already. Access superglobals without +checking to see if certain indexes are set first and pass default values, use a +nicely formatted var dump, validate emails, generate random strings, flatten an +array, pull a single column out of a multidimensional array and much more. + +Although it's implemented as one giant class, util.php has extensive +documentation and a full suite of unit tests to avoid breaking +backwards-compatibility unintentionally. + +## Release Information + +This repo contains in development code for future releases as well as the +current stable branch. Development code is contained in the develop branch. + +## Changelog and New Features + +You can find a list of all changes for each release in the +[official documentation](http://brandonwamboldt.github.com/utilphp/#changelog) + +## Installation + +### Server Requirements + +* PHP version 5.3.3 or higher. + +### Standalone File + +Simply drop `util.php` in any project and call `include 'util.php';` in your +project. You can then access the `Util` class. + +### Composer + +Add the following dependency to your composer.json: + +``` +"brandonwamboldt/utilphp": "1.0.*" +``` + +When used with composer, the class is namespaced (`\utilphp\util`) instead of +just `util`. + +## Contributing + +UtilPHP is a community driven project and accepts contributions of code and +documentation from the community. These contributions are made in the form of +Issues or [Pull Requests](http://help.github.com/send-pull-requests/) on the +[UtilityPHP repository](https://github.com/brandonwamboldt/utilphp) on GitHub. + +Issues are a quick way to point out a bug. If you find a bug or documentation +error in UtilityPHP then please check a few things first: + +* There is not already an open Issue +* The issue has already been fixed (check the develop branch, or look for closed Issues) +* Is it something really obvious that you fix it yourself? + +Reporting issues is helpful but an even better approach is to send a Pull +Request, which is done by "Forking" the main repository and committing to your +own copy. This will require you to use the version control system called Git. + +## Guidelines + +Before we look into how, here are the guidelines. If your Pull Requests fail to +pass these guidelines it will be declined and you will need to re-submit when +you’ve made the changes. This might sound a bit tough, but it is required for +me to maintain quality of the code-base. + +### PHP Style + +Please ensure all new contributions match the [PSR-2](http://www.php-fig.org/psr/psr-2/) +coding style guide. + +### Documentation + +If you change anything that requires a change to documentation then you will +need to add it. New methods, parameters, changing default values, adding +constants, etc are all things that will require a change to documentation. The +change-log must also be updated for every change. Also PHPDoc blocks must be +maintained. + +### PHP Version Compatibility + +UtilityPHP is compatible with PHP 5.3.3 so all code supplied must stick to this +requirement. + +Of particular note is avoiding short array notation like this: + +``` +$var = []; +``` + +Please use the old notation instead: + +``` +$var = array(); +``` + +I know it's uglier, but PHP 5.3 while EOL'd, still isn't that old. + +### Branching + +One thing at a time: A pull request should only contain one change. That does +not mean only one commit, but one change - however many commits it took. The +reason for this is that if you change X and Y but send a pull request for both +at the same time, we might really want X but disagree with Y, meaning we cannot +merge the request. Using the Git-Flow branching model you can create new +branches for both of these features and send two requests. + +## License + +UtilPHP is licensed under the MIT license. + +## Resources + +* [Documentation](http://brandonwamboldt.github.com/utilphp/) diff --git a/e_lib/utilphp-1.1.0/composer.json b/e_lib/utilphp-1.1.0/composer.json new file mode 100644 index 00000000..9bf3520e --- /dev/null +++ b/e_lib/utilphp-1.1.0/composer.json @@ -0,0 +1,24 @@ +{ + "name": "brandonwamboldt/utilphp", + "type": "library", + "version": "1.1.0", + "description": "util.php is a collection of useful functions and snippets that you need or could use every day, designed to avoid conflicts with existing projects", + "keywords": ["php", "utility", "collection", "helpers"], + "homepage": "https://github.com/brandonwamboldt/utilphp", + "license": "MIT", + "authors": [ + { + "name": "Brandon Wamboldt", + "email": "brandon.wamboldt@gmail.com" + } + ], + "autoload": { + "psr-0": { "utilphp\\": "src/" } + }, + "require-dev": { + "satooshi/php-coveralls": "dev-master" + }, + "require": { + "php": ">=5.3.3" + } +} diff --git a/e_lib/utilphp-1.1.0/docs/css/docs.css b/e_lib/utilphp-1.1.0/docs/css/docs.css new file mode 100644 index 00000000..77993435 --- /dev/null +++ b/e_lib/utilphp-1.1.0/docs/css/docs.css @@ -0,0 +1,168 @@ +body { + background: #f4f4f4 url('../images/background.png'); + color: #333; + font: 18px/30px "Droid Serif", "Helvetica Neue", Helvetica, Arial; +} + +a { + text-decoration: none; + color: #f00; + padding: 2px; +} + +a:hover { + background: #277585; + color: #fff; + border-radius: 3px; +} + +h1, h2, h3, h4, h5, h6 { + padding-top: 20px; +} + +h2 { + font-size: 40px; + font-weight: normal; + margin: 0 0 15px; +} + +p { + margin: 20px 0; + min-width: 550px; + max-width: 900px; +} + +table, tr, td { + margin: 0; padding: 0; +} + +td { + padding: 2px 12px 2px 0; +} + +ul { + list-style-type: circle; + padding: 0 0 0 20px; +} + +li { + width: 500px; + margin-bottom: 10px; +} + +code, pre, tt { + font-family: Monaco, Consolas, "Lucida Console", monospace; + font-size: 12px; + line-height: 18px; + font-style: normal; +} + +tt { + padding: 0px 3px; + background: #fff; + border: 1px solid #ddd; + zoom: 1; +} + +code { + margin-left: 20px; +} + +pre { + font-size: 12px; + padding: 12px; + background: #fff; + margin: 0px 0 30px; + border-radius: 0 0 2px 2px; + box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); +} + +span.header { + font-size: 24px; + line-height: 30px; + border-left: 10px solid #ddd; + padding-left: 10px; +} + +.desc-text code { + margin-left: 0; + font-size: 18px; + color: #0E04C8; +} + +#sidebar { + background: #fff; + position: fixed; + top: 0; left: 0; bottom: 0; + width: 220px; + overflow-y: auto; + overflow-x: hidden; + padding: 5px 0 30px 10px; + border-right: 1px solid #bbb; + + box-shadow: 0 0 20px #ccc; + -webkit-box-shadow: 0 0 20px #ccc; + -moz-box-shadow: 0 0 20px #ccc; + -webkit-overflow-scrolling: touch; +} + +.toc_title, .toc_title:visited { + display: block; + color: #000; + margin-top: 15px; +} + +.toc_title:hover { + background: none; + color: #f00; +} + +.toc_title .version { + font-size: 12px; + font-weight: normal; +} + +.toc_section { + font-size: 14px; + line-height: 24px; + margin: 5px 0 0 0; + padding-left: 10px; + list-style-type: none; +} + +.toc_section li { + cursor: pointer; + margin: 0 0 3px 0; +} + +.toc_section li a { + text-decoration: none; + color: black; +} + +.toc_section li a:hover { + background: none; + color: #f00; +} + +.container { + min-width: 550px; + max-width: 1000px; + margin: 40px 0 50px 260px; +} + +#documentation section > article > p > code { + color: #999; +} + +#documentation section > article > p > code > .util_class { + color: #bbb; +} + +#documentation section > article > p > code > .func_name { + color: #0E04C8; +} + +#documentation section > article > p > code > .param { + color: #DA72F3; +} diff --git a/e_lib/utilphp-1.1.0/docs/favicon.png b/e_lib/utilphp-1.1.0/docs/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..5f17cf1dbd24f03f46089ef35b6078c8a09aeee8 GIT binary patch literal 803 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 z�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 literal 0 HcmV?d00001 diff --git a/e_lib/utilphp-1.1.0/docs/images/background.png b/e_lib/utilphp-1.1.0/docs/images/background.png new file mode 100644 index 0000000000000000000000000000000000000000..1e6fddd7dfd3e43f9a6ff7fa5c4aa3eb2ca6275d GIT binary patch literal 1028 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 at&X`!7td+Kk+sfrr)3JUFsd_jPy81`G + + + + + + + + + + + + + + + util.php - The PHP programmers best friend - UtilityPHP + + + +

+ +
+

+ +

+ +

+ util.php is a collection of useful functions and snippets + that you need or could use every day. It's implemented as a class with static methods, to avoid conflicts with your + existing code-base. Just drop it in and start using it immediately. +

+ +

+ Included are 60+ functions that provide you with the ability to do common tasks much easier and more efficiently, + without having to find that one comment on php.net where you know its been done already. Access superglobals + without checking to see if certain indexes are set first and pass default values, use a nicely formatted var dump, + validate emails, generate random strings, flatten an array, pull a single column out of a multidimensional array + and much more. +

+ +

+ Although it's implemented as one giant class, util.php has extensive documentation and a full suite of unit tests + to avoid breaking backwards-compatibility unintentionally. +

+ +

+ The project is hosted on GitHub. + You can report bugs and discuss features on the + issues page, + or send tweets to @brandonwamboldt. +

+ +

Downloads (Right-click, and use "Save As")

+ +

+ Stable Version (1.1.0)
+ Unstable Version (master) +

+ +

Installation

+ + Server Requirements
+ +
    +
  • PHP 5.3.3+
  • +
+ + Standalone File
+ +

+ Simply drop util.php in any project and call include 'util.php'; in your project. + You can then access the Util class. +

+ + Composer
+ +

+ Add the following dependency to your composer.json: + +

"brandonwamboldt/utilphp": "1.1.*"
+ + When used with composer, the class is namespaced (\utilphp\util) instead of + just util. +

+ +
+

Debugging Functions

+ +
+
+

+ var_dump + + util::var_dump(mixed $var[, bool $return = FALSE]) + +

+ +

+ Nicely prints out the contents of a passed variable. Booleans are properly displayed as 'true' or 'false', + null values are shown as 'NULL', variable types are displayed, and arrays and objects are displayed as a + collapsible tree powered by JavaScript. +

+ +

Usage:

+ +
util::var_dump($var);
+ + +
+
+ +

Array/Object Functions

+ +
+
+

+ array_first + + util::array_first(array $array) + +

+ +

+ Retrieve the first value from an array. Can be run on function callbacks, and it will not modify the pointer + of the source array unlike most other methods of doing this. +

+ +

Usage:

+ +
util::array_first( ['a', 'b', 'c'] );
=> Returns 'a'
+
+ +
+

+ array_first_key + + util::array_first_key(array $array) + +

+ +

+ Retrieve the first key from an array. Can be run on function callbacks, and it will not modify the pointer of + the source array unlike most other methods of doing this. +

+ +

Usage:

+ +
util::array_first_key( $users );
=> Returns 'brandon'
+
+ +
+

+ array_flatten + + util::array_flatten(array $array[, bool $preserve_keys = TRUE]) + +

+ +

Flattens a multi-dimensional array into a one dimensional array

+ +

Usage:

+ +
util::array_flatten( [ 'a', 'b', [ 'c', 'd', 'e', [ 'f', 'g', [ [ [ [ 'h', 'i', 'j' ] ] ] ] ] ] ] );
+=> Returns [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]
+
+ +
+

+ array_get + + util::array_get($var[, mixed $default = NULL]) + +

+ +

Retrieve a value from an array, or return a given default if the index isn't set

+ +

Usage:

+ +
util::array_get($_POST['action'], 'index');
+=> If $_POST['action'] is set, returns its value, otherwise returns 'index'
+util::array_get($_POST['action']['do'], 'index');
+=> Returns the value of $_POST['action']['do'] or 'index'
+
+ +
+

+ array_last + + util::array_last(array $array) + +

+ +

+ Retrieve the last value from an array. Can be run on function callbacks, and it will not modify the pointer + of the source array unlike most other methods of doing this. +

+ +

Usage:

+ +
util::array_last( [ 'a', 'b', 'c'] );
+=> Returns 'c'
+
+ +
+

+ array_last_key + + util::array_last_key(array $array) + +

+ +

+ Retrieve the last key from an array. Can be run on function callbacks, and it will not modify the pointer of + the source array unlike most other methods of doing this. +

+ +

Usage:

+ +
util::array_last_key( $users );
+=> Returns 'zane'
+
+ +
+

+ array_map_deep + + util::array_map_deep(array $array, callable $callback[, bool $on_nonscalar = FALSE]) + +

+ +

+ Returns an array containing all the elements of $array after applying the callback function to each one recursively. + Particularly useful for avoiding errors when calling functions that only accept scalar values on an array that could + contain nested arrays, such as $_GET or $_POST. +

+ +

Usage:

+ +
util::array_map_deep($_POST, 'htmlentities');
+=> Recursively escapes each scalar value in $_POST
+util::array_map_deep($_POST, 'htmlentities', TRUE);
+=> Recursively escapes each value in $_POST regardless of its type
+
+ +
+

+ array_pluck + + util::array_pluck(array $array, string $field[, bool $preserve_keys, bool $remove_nomatches]) + +

+ +

+ Replaces each value in an array with the specified field of the array or object that used to be the value. Very + useful when you have an array of objects or arrays from a database, and you only want one specific field. For + example, you want an array of emails from an array of users. +

+ +

Usage:

+ +
util::array_pluck([['val' => 1], ['val' => 2], ['val' => 3]], 'val');
+=> Returns [1, 2, 3]
+util::array_pluck($users, 'email');
+=> Returns an array of email addresses for each user
+
+ +
+

+ array_search_deep + + util::array_search_deep(array $array, mixed $search[, string $field = FALSE]) + +

+ +

+ Allows you to search for a value in an array of arrays or an array of objects, and return the key of the value + that matches the search criteria. If $field is unspecified, the entire array/object is searched. +

+ +

Usage:

+ +
util::array_search_deep($_POST, 'delete_post');
+=> Might return 'do' if $_POST['do']['action'] = 'delete_post'
+util::array_search_deep($users, 'rogue_coder', 'username');
+=> Might return 5 if $users[5]->username = 'rogue_coder'
+
+ +
+

+ array_clean + + util::array_clean(array $array) + +

+ +

+ Remove all null/empty/false values from the given array. +

+ +

Usage:

+ +
util::array_clean( array( 'a', 'b', '', null, false, 0) );
=> Returns array('a', 'b');
+
+ +
+ +

URL Functions

+ +
+
+

+ add_query_arg + + util::add_query_arg() + +

+ +

Adds one ore more query args to the query string of the current URL or a given URL

+ +

Usage:

+ +
util::add_query_arg( 'user', '5', '/admin/users?action=edit' );
+=> Returns '/admin/users?action=edit&user=5'
+util::add_query_arg( [ 'user' => 5, 'action' => 'edit' ], '/admin/users' );
+=> Returns '/admin/users?user=5&action=edit'
+
+ +
+

+ get_current_url + + util::get_current_url() + +

+ +

Returns the current URL with hostname

+ +

Usage:

+ +
util::get_current_url();
+=> Returns 'http://brandonwamboldt.ca/utilphp/'
+
+ +
+

+ is_https + + util::is_https() + +

+ +

Returns true if the current page is being loaded over https, false if it isn't

+ +

Usage:

+ +
util::is_https();
+=> Returns false
+
+ +
+

+ http_build_url + + util::http_build_url([mixed $url[, mixed $parts[, int $flags = HTTP_URL_REPLACE[, array &amo;$new_url]]]]) + +

+ +

+ Pure PHP implementation/polyfill for http_build_url + which requires pecl_http to be installed. +

+ +

Usage:

+ +
echo util::http_build_url("http://user@www.example.com/pub/index.php?a=b#files",
+    array(
+        "scheme" => "ftp",
+        "host" => "ftp.example.com",
+        "path" => "files/current/",
+        "query" => "a=c"
+    ),
+    HTTP_URL_STRIP_AUTH | HTTP_URL_JOIN_PATH | HTTP_URL_JOIN_QUERY | HTTP_URL_STRIP_FRAGMENT
+);
+ +

The above example will output:

+ +
ftp://ftp.example.com/pub/files/current/?a=c
+
+ +
+

+ is_https + + util::is_https() + +

+ +

Returns true if the current page is being loaded over https, false if it isn't

+ +

Usage:

+ +
util::is_https();
+=> Returns false
+
+ +
+

+ remove_query_arg + + util::remove_query_arg( array|string $query_args[, string $url]) + +

+ +

Removes one ore more query args from the query string of the current URL or a given URL

+ +

Usage:

+ +
util::remove_query_arg( 'action', '/admin/users?action=edit&user=5' );
+=> Returns '/admin/users?user=5'
+util::remove_query_arg( [ 'user', 'action'], '/admin/users?action=edit&user=5' );
+=> Returns '/admin/users'
+
+ +
+

+ slugify + + util::slugify(string $string[, string $separator = "-", bool $css_mode = FALSE]) + +

+ +

+ Generate a string safe for use in URLs from any given string. Converts any accent characters + to their equivalent normal characters and converts any other non-alphanumeric characters to + dashes, then converts any sequence of two or more dashes to a single dash. This function + generates slugs safe for use as URLs, and if you pass TRUE as the second parameter, it will + create strings safe for use as CSS classes or IDs. +

+ +

Usage:

+ +
util::slugify('This is a random --string with an Ãccent');
+=> Returns 'this-is-a-random-string-with-an-accent'
+util::slugify('Another String', '.');
+=> Returns 'another.string'
+
+
+ +

String Functions

+ +
+
+

+ htmlentities + + util::htmlentities(string $string[, bool $preserve_encoded_entities = FALSE]) + +

+ +

+ Executes htmlentities with ENT_QUOTES set by default. However, if you pass TRUE as + the second parameter, it will not re-encode entities that are already encoded. +

+ +

Usage:

+ +
util::htmlentities('this string < this string', TRUE);
+=> Returns 'this string < this string'
+
+ +
+

+ htmlspecialchars + + util::htmlspecialchars(string $string[, bool $preserve_encoded_entities = FALSE]) + +

+ +

+ Executes htmlspecialchars with ENT_QUOTES set by default. However, if you pass TRUE as + the second parameter, it will not re-encode entities that are already encoded. +

+ +

Usage:

+ +
util::htmlspecialchars('this string < this string', TRUE);
+=> Returns 'this string < this string'
+
+ +
+

+ linkify + + util::linkify(string $text) + +

+ +

Find's any URLs in the specified text and wraps them with HTML anchor tags

+ +

Usage:

+ +
util::linkify('this string has a link to www.google.com');
+=> Returns 'this string has a link to <a href="http://wwww.google.com/">www.google.com</a>'
+
+ +
+

+ match_string + + util::match_string(string $pattern, string $string[, bool $caseSensitive = true]) + +

+ +

+ Check if a string matches a given pattern. You can use '*' as a wildcard character. +

+ +

Usage:

+ +
util::match_string("test/*", "test/my/test");
+=> Returns true
+util::match_string("test/", "test/my/test");
+=> Returns false
+
+ +
+

+ random_string + + util::random_string(int $length[, bool $human_friendly = TRUE, bool $include_symbols = FALSE, bool $no_duplicate_chars = FALSE]) + +

+ +

+ Generates a random string of the specified length. Human friendly mode + will exclude characters that can be confused with other characters, such + as 0 (zero) and O (capital o), 1 (one) and l (lowercase L). +

+ +

Usage:

+ +
util::random_string(8);
+=> Returns 'a6BiF4UW'
+
+ +
+

+ number_to_word + + util::number_to_word(int|float $number) + +

+ +

Converts a number into its text equivalent. For example, 56 becomes fifty-six.

+ +
util::number_to_word(512.5);
+=> Returns 'five hundred and twelve point five'
+
+ +
+

+ ordinal + + util::ordinal(int $number) + +

+ +

Returns the ordinal version of a number (appends th, st, nd, rd)

+ +

Usage:

+ +
util::ordinal(22);
+=> Returns '22nd'
+
+ +
+

+ remove_accents + + util::remove_accents(string $string) + +

+ +

Converts all accent characters to their ASCII equivalents

+ +

Usage:

+ +
util::remove_accents('Àccent');
+=> Returns 'Accent'
+
+ +
+

+ secure_random_string + + util::secure_random_string(int $length) + +

+ +

Generate a random string of characters. Will attempt to use a secure source (openssl).

+ +

Usage:

+ +
util::secure_random_string(16);
+=> Returns '5bB1RJH0cQhNjviT'
+
+ +
+

+ seems_utf8 + + util::seems_utf8(string $string) + +

+ +

Checks to see if a given string is UTF-8 encoded/safe

+ +

Usage:

+ +
util::seems_utf8('This is some random string user input');
+=> Returns true
+
+ +
+

+ safe_truncate + + util::safe_truncate(string $string, int $length[, string $append = '...']) + +

+ +

Truncate a string to a specified length without cutting a word off

+ +

Usage:

+ +
util::safe_truncate('The quick brown fox jumps over the lazy dog', 24);
+=> Returns 'The quick brown fox...'
+
+ +
+

+ size_format + + util::size_format(int $bytes[, int $decimals = 0]) + +

+ +

Formats an integer as a human friendly size string, such as 4 KiB.

+ +

Usage:

+ +
util::size_format( 25151251, 2 );
+=> Returns '23.99 MiB'
+
+ +
+

+ str_to_bool + + util::str_to_bool(string $string) + +

+ +

Converts a string to boolean, looking for yes/no words like 'yes', 'no', 'true', 'false', 'y', 'n', etc

+ +

Usage:

+ +
util::str_to_bool('yes');
+=> Returns true
+
+ +
+

+ zero_pad + + util::zero_pad(int $number, int $length) + +

+ +

Pads a given number with zeroes on the left

+ +

Usage:

+ +
util::zero_pad(341, 8);
+=> Returns '00000341'
+
+ +
+

+ strip_space + + util::strip_space(string $string) + +

+ +

Strip all withspace from the given string

+ +

Usage:

+ +
util::strip_space(' The quick brown fox jumps over the lazy dog ');
+=> Returns 'Thequickbrownfoxjumpsoverthelazydog'
+
+ +
+

+ sanitize_string + + util::sanitize_string(string $string) + +

+ +

+ Sanitize a string by performing the following operation : +

    +
  • Remove accents
  • +
  • Lower the string
  • +
  • Remove punctuation characters
  • +
  • Strip whitespaces
  • +
+ +

+

Usage:

+ +
util::sanitize_string(' Benoit! à New-York? j’ai perçu 1 % : Qu’as-tu "gagné" chez M. V. Noël? Dix francs.');
+=> Returns 'benoitanewyorkjaipercu1quastugagnechezmvnoeldixfrancs'
+
+
+ +

Files

+ +
+
+

+ full_permissions + + util::full_permissions(string $file) + +

+ +

Returns the file permissions as a nice string, like -rw-r--r--

+ +

Usage:

+ +
util::full_permissions('/etc/passwd');
+=> Returns '-rw-r--r--'
+
+ +
+

+ rmdir + + util::rmdir(string $dir[, bool $traverseSymlinks = false]) + +

+ +

Recursively deletes a directories (including all contents).

+ +

Usage:

+ +
util::rmdir('/tmp/working/dir');
+=> Returns true
+
+
+ +

Serialization

+ +
+
+

+ is_serialized + + util::is_serialized(mixed $data) + +

+ +

Checks to see if a given variable is a seralized data structure

+ +

Usage:

+ +
util::is_serialized( 'a:0:{}' );
+=> Returns true
+
+ +
+

+ maybe_serialize + + util::maybe_serialize(mixed $data) + +

+ +

Serialize data, if needed to store in plaintext (Arrays or objects)

+ +

Usage:

+ +
util::maybe_serialize( 5 );
+=> Returns 5
+util::maybe_serialize( array() );
+=> Returns 'a:0:{}'
+
+ +
+

+ maybe_unserialize + + util::maybe_unserialize(mixed $data) + +

+ +

Unserialize data, if it's a serialized string

+ +

Usage:

+ +
util::maybe_unserialize(5);
+=> Returns 5
+util::maybe_unserialize("a:0:{}");
+=> Returns array()
+
+ +
+

+ fix_broken_serialization + + util::fix_broken_serialization(mixed $data) + +

+ +

+ Attempt to fix a broken serialization string (e.g. where string offsets are incorrect). Can fix + errors that frequently occur with mismatched character sets or higher-than-ASCII characters. +

+ +

Usage:

+ +
util::fix_broken_serialization('a:1:{s:4:"test";s:4:"abc";}');
+=> Returns 'a:1:{s:4:"test";s:3:"abc";}'
+
+
+ +

Other

+ +
+
+

+ force_download + + util::force_download(string $filename, string $content = FALSE) + +

+ +

+ Transmit headers that force a browser to display the download file dialog. Cross + browser compatible. Only fires if headers have not already been sent. +

+ +

Usage:

+ +
util::force_download( 'export.csv', file_get_contents( 'securefile.csv' ) );
+=> The user will be prompted to download the file
+
+ +
+

+ get_client_ip + + util::get_client_ip(bool $trust_proxy_headers = FALSE) + +

+ +

+ Returns the IP address of the client. Only enable $trust_proxy_headers if your server is behind a proxy + that sets the HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR headers. +

+ +

Usage:

+ +
util::get_client_ip();
+=> Returns '12.123.12.100'
+
+ +
+

+ get_gravatar + + util::get_gravatar(string $email, int $size = 32) + +

+ +

Return the URL to a user's gravatar

+ +

Usage:

+ +
util::get_gravatar('brandon.wamboldt@gmail.com');
+=> Returns 'http://www.gravatar.com/avatar/46679faeb6780ecb1ea57527fdc66eb3?s=32'
+
+ +
+

+ human_time_diff + + util::human_time_diff(int $from, int $to = '', int $as_text = FALSE, string $suffix = ' ago') + +

+ +

Converts a unix timestamp to a relative time string, such as "3 days ago" or "2 weeks ago"

+ +

Usage:

+ +
util::human_time_diff(time() - 7400);
+=> Returns '2 hours ago'
+util::human_time_diff(time() - 7400, '', TRUE);
+=> Returns 'two hours ago'
+
+ +
+

+ nocache_headers + + util::nocache_headers(mixed $data) + +

+ +

Sets the headers to prevent caching for the different browsers

+ +

+ Different browsers support different nocache headers, so several headers must be sent + so that all of them get the point that no caching should occur +

+ +

Usage:

+ +
util::nocache_headers();
+
+ +
+

+ utf8_headers + + util::utf8_headers(mixed $content_type = 'text/html') + +

+ +

Transmit UTF-8 content headers if the headers haven't already been sent

+ +

Usage:

+ +
util::utf8_headers();
+
+ +
+

+ validate_email + + util::validate_email(string $possible_email) + +

+ +

Validate an email address

+ +

Usage:

+ +
util::validate_email( 'brandon.wamboldt@gmail.com' );
+=> Returns true
+util::validate_email( 'not an email' );
+=> Returns false
+
+
+ +

Constants

+ +
+
+

+ SECONDS_IN_A_MINUTE + + util::SECONDS_IN_A_MINUTE + +

+ +

The number of seconds in a minute, useful for making code more verbose

+
+ +
+

+ SECONDS_IN_AN_HOUR + + util::SECONDS_IN_AN_HOUR + +

+ +

The number of seconds in an hour, useful for making code more verbose

+
+ +
+

+ SECONDS_IN_A_DAY + + util::SECONDS_IN_A_DAY + +

+ +

The number of seconds in a day, useful for making code more verbose

+
+ +
+

+ SECONDS_IN_A_WEEK + + util::SECONDS_IN_A_WEEK + +

+ +

The number of seconds in a week (7 days), useful for making code more verbose

+
+ +
+

+ SECONDS_IN_A_MONTH + + util::SECONDS_IN_A_MONTH + +

+ +

The number of seconds in a month (30 days), useful for making code more verbose

+
+ +
+

+ SECONDS_IN_A_YEAR + + util::SECONDS_IN_A_YEAR + +

+ +

The number of seconds in a year (365 days), useful for making code more verbose

+
+
+ +

Change Log

+ + + +

+ 1.1.0
+ + This release introduces a deprecation notice for slugify(), please update your code.

+ + - Added a cryptographically secure random string function secure_random_string. Thanks to @abhimanyusharma003 via Pull Request #53
+ - Added limit_characters and limit_words functions. Thanks to @abhimanyusharma003 via Pull Request #55
+ - Added rmdir method to recursively delete a directory. Thanks to @ARACOOOL via Pull Request #56
+ - Added set_executable, set_readable, set_writable, directory_size, directory_contents and get_user_dir functions. Thanks to @sergserg via Pull Request #70
+ - Changed parameter ordering for slugify, $css_mode is now the third argument. For backwards compatibility, the old order will still work but it will generate an E_USER_DEPRECATED warning. Thanks to @abhimanyusharma003 via Pull Request #71
+ - Added match_string method. Thanks to @abhimanyusharma003 via Pull Request #72
+ - Renamed internal methods (protected ones) for PSR-2 compliance
+ - General performance improvements, code quality improvements, and increased unit test coverage (special thanks to @hopeseekr for getting us near 100% coverage)
+

+ +

+ 1.0.7
+ - Added fix_broken_serialization to fix broken serialized strings (Thanks to @hopeseekr via Pull Request #48)
+ - Fixed get_current_url appending port 80 or 443 when not needed (Thanks to @scottchiefbaker via Pull Request #49)
+ - var_dump can now handle recursive data structures without crashing
+ - var_dump code was minified and cleaned up
+ - array_flatten was optimized (thanks to @hopeseekr via Pull Request #47)
+ - remove_accents was completely rewritten and is now ~4x faster
+

+ +

+ 1.0.6
+ - Added start_with function
+ - Added ends_with function
+ - Added str_contains function
+ - Added str_icontains function
+ - Added get_file_ext function
+ - Fixing permissions on the files & directories
+ - Fixing a bug with the include path of util.php
+

+ +

+ 1.0.5
+ - Issue #29 Fixed error in var_dump if mbstring extension wasn't present
+ - Adding Composer support
+ - Updating license from GPL to MIT
+ - Adding Changelog to project
+ - Bumping minimum version to PHP 5.3.3
+

+ +

+ 1.0.4
+ - Issue #22 Removed all superglobal *_get functions, you can use the modified array_get now
+ - Issue #22 Modifed the behaviour of array_get, see documentation
+ - Pull Request #21 Added multibyte support to html* functions
+ - Issue #9 Removed the str_to_utf8 function
+ - Issue #3 Removed the absint function
+ - Removed declare() from util.php to avoid errors
+ - Updated PHPUnit tests to use PHPUnit 3.6 +

+ +

+ 1.0.3
+ - Issue #16 Improved performance of slugify
+ - Issue #14 Modified the regex for seems_utf8 to be more accurate
+ - Issue #13 Changed validate_email to be wrapper for filter_var
+ - Added 'ok' to the list of yes words for str_to_bool
+ - str_to_bool matches no followed by any number of 'o's +

+ +

+ 1.0.2
+ - Issue #12 get_current_url now includes the port and user/password if required
+ - Issue #11 human_time_diff now uses the DateTime functions
+ - Issue #10 is_https no longer checks the port as well +

+ +

+ 1.0.1
+ - Issue #7 Added the $trust_proxy_headers parameter to get_client_ip
+ - Issue #6 Removed is_isset as the function did not work as intended
+ - Issue #6 Removed is_empty as it is redundant, use ! with function calls instead
+ - Fixed a bug with get_gravatar +

+ +

+ 1.0.0
+ Initial release of util.php. +

+
+
+ + + diff --git a/e_lib/utilphp-1.1.0/phpunit.xml.dist b/e_lib/utilphp-1.1.0/phpunit.xml.dist new file mode 100644 index 00000000..d4b9366c --- /dev/null +++ b/e_lib/utilphp-1.1.0/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + ./tests + + + + + ./src + + + + + + \ No newline at end of file diff --git a/e_lib/utilphp-1.1.0/tests/README.md b/e_lib/utilphp-1.1.0/tests/README.md new file mode 100644 index 00000000..e81d26c3 --- /dev/null +++ b/e_lib/utilphp-1.1.0/tests/README.md @@ -0,0 +1,39 @@ +# UtilityPHP Unit Tests # + +### Introduction + +This is the testing documentation for util.php. The unit tests require PHPUnit, +and can be run in your web browser. + +### Requirements + +PHP Unit >= 3.5.6 + +#### Installation of PHPUnit + + # Download the PHPUnit phar. + wget https://phar.phpunit.de/phpunit.phar + + # You can just run it locally. (Preferred for Windows) + php phpunit.phar --version + + # Or install it system-wide. + mv phpunit.phar phpunit + chmod +x phpunit + sudo mv phpunit /usr/local/bin + phpunit --version + +## Test Suites: + +util.php includes a phpunit config file, so just run `phpunit` from the working +directory to run the test suite. + +``` +phpunit +``` + +If you want code coverage reports, use the following: + +``` +phpunit --coverage-html ./report +``` diff --git a/e_lib/utilphp-1.1.0/tests/UtilTest.php b/e_lib/utilphp-1.1.0/tests/UtilTest.php new file mode 100644 index 00000000..404cf7bd --- /dev/null +++ b/e_lib/utilphp-1.1.0/tests/UtilTest.php @@ -0,0 +1,1183 @@ +data = (object)array('a', 'b', 'c'); + } +} + +/** + * PHPUnit test case for the util.php library + * + * @author Brandon Wamboldt + * @since 1.0.000 + */ +class UtilityPHPTest extends PHPUnit_Framework_TestCase +{ + /** + * Allows for the testing of private and protected methods. + * + * @param $name + * @return \ReflectionMethod + */ + protected static function getMethod($name) + { + $class = new \ReflectionClass('util'); + $method = $class->getMethod($name); + $method->setAccessible(true); + return $method; + } + + public function test_array_get() + { + $_GET = array(); + $_GET['abc'] = 'def'; + $_GET['nested'] = array( 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3' ); + + // Looks for $array['abc'] + $this->assertEquals( 'def', util::array_get( $_GET['abc'] ) ); + + // Looks for $array['nested']['key2'] + $this->assertEquals( 'val2', util::array_get( $_GET['nested']['key2'] ) ); + + // Looks for $array['doesnotexist'] + $this->assertEquals( 'defaultval', util::array_get( $_GET['doesnotexist'], 'defaultval' ) ); + } + + public function test_slugify() + { + $this->assertEquals( 'a-simple-title', util::slugify( 'A simple title' ) ); + $this->assertEquals( 'this-post-it-has-a-dash', util::slugify( 'This post -- it has a dash' ) ); + $this->assertEquals( '123-1251251', util::slugify( '123----1251251' ) ); + $this->assertEquals( 'one23-1251251', util::slugify( '123----1251251', '-', true ) ); + + $this->assertEquals( 'a-simple-title', util::slugify( 'A simple title', '-' ) ); + $this->assertEquals( 'this-post-it-has-a-dash', util::slugify( 'This post -- it has a dash', '-' ) ); + $this->assertEquals( '123-1251251', util::slugify( '123----1251251', '-' ) ); + $this->assertEquals( 'one23-1251251', util::slugify( '123----1251251', '-', true ) ); + + $this->assertEquals( 'a_simple_title', util::slugify( 'A simple title', '_' ) ); + $this->assertEquals( 'this_post_it_has_a_dash', util::slugify( 'This post -- it has a dash', '_' ) ); + $this->assertEquals( '123_1251251', util::slugify( '123----1251251', '_' ) ); + $this->assertEquals( 'one23_1251251', util::slugify( '123----1251251', '_', true ) ); + + // Blank seperator test + $this->assertEquals( 'asimpletitle', util::slugify( 'A simple title', '' ) ); + $this->assertEquals( 'thispostithasadash', util::slugify( 'This post -- it has a dash', '' ) ); + $this->assertEquals( '1231251251', util::slugify( '123----1251251', '' ) ); + $this->assertEquals( 'one231251251', util::slugify( '123----1251251', '', true ) ); + + // Test old parameter ordering for backwards compatability + error_reporting(E_ALL ^ E_USER_DEPRECATED); + $this->assertEquals( 'one23-1251251', util::slugify( '123----1251251', true ) ); + $this->assertEquals( '123-1251251', util::slugify( '123----1251251', false ) ); + } + + public function test_seems_utf8() + { + // Test a valid UTF-8 sequence: "ÜTF-8 Fµñ". + $validUTF8 = "\xC3\x9CTF-8 F\xC2\xB5\xC3\xB1"; + $this->assertTrue( util::seems_utf8( $validUTF8 ) ); + + $this->assertTrue( util::seems_utf8( "\xEF\xBF\xBD this has \xEF\xBF\xBD\xEF\xBF\xBD some invalid utf8 \xEF\xBF\xBD" ) ); + + // Test invalid UTF-8 sequences + $invalidUTF8 = "\xc3 this has \xe6\x9d some invalid utf8 \xe6"; + $this->assertFalse( util::seems_utf8( $invalidUTF8 ) ); + + // And test some plain ASCII + $this->assertTrue( util::seems_utf8( 'The quick brown fox jumps over the lazy dog' ) ); + + // Test an invalid non-UTF-8 string. + if (function_exists('mb_convert_encoding')) { + mb_internal_encoding('UTF-8'); + // Converts the 'ç' UTF-8 character to UCS-2LE + $utf8Char = pack('n', 50087); + $ucsChar = mb_convert_encoding($utf8Char, 'UCS-2LE', 'UTF-8'); + + // Ensure that PHP's internal encoding system isn't malconfigured. + $this->assertEquals( $utf8Char, 'ç', 'This PHP system\'s internal character set is not properly set as UTF-8.' ); + $this->assertEquals( $utf8Char, pack('n', 50087), 'Something is wrong with your ICU unicode library.' ); + + // Test for not UTF-8. + $this->assertFalse( util::seems_utf8( $ucsChar) ); + + // Test the worker method. + $method = self::getMethod('seemsUtf8Regex'); + $this->assertFalse($method->invoke(null, $invalidUTF8), 'util::seemsUtf8Regex did not properly detect invalid UTF-8.'); + $this->assertTrue($method->invoke(null, $validUTF8), 'util::seemsUtf8Regex did not properly detect valid UTF-8.'); + } + } + + public function test_size_format() + { + $size = util::size_format( 512, 0 ); + $this->assertEquals( '512 B', $size ); + + $size = util::size_format( 2048, 1 ); + $this->assertEquals( '2.0 KiB', $size ); + + $size = util::size_format( 25151251, 2 ); + $this->assertEquals( '23.99 MiB', $size ); + + $size = util::size_format( 19971597926, 2 ); + $this->assertEquals( '18.60 GiB', $size ); + + $size = util::size_format( 2748779069440, 1 ); + $this->assertEquals( '2.5 TiB', $size ); + + $size = util::size_format( 2.81475e15, 1 ); + $this->assertEquals( '2.5 PiB', $size ); + + $size = util::size_format( 2.81475e19, 1 ); + $this->assertEquals( '25000.0 PiB', $size ); + } + + public function test_maybe_serialize() + { + $obj = new stdClass(); + $obj->prop1 = 'Hello'; + $obj->prop2 = 'World'; + + $this->assertEquals( 'This is a string', util::maybe_serialize( 'This is a string' ) ); + $this->assertEquals( 5.81, util::maybe_serialize( 5.81 ) ); + $this->assertEquals( 'a:0:{}', util::maybe_serialize( array() ) ); + $this->assertEquals( 'O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}', util::maybe_serialize( $obj ) ); + $this->assertEquals( 'a:4:{i:0;s:4:"test";i:1;s:4:"blah";s:5:"hello";s:5:"world";s:5:"array";O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}}', util::maybe_serialize( array( 'test', 'blah', 'hello' => 'world', 'array' => $obj ) ) ); + } + + public function test_maybe_unserialize() + { + $obj = new stdClass(); + $obj->prop1 = 'Hello'; + $obj->prop2 = 'World'; + + $this->assertNull(util::maybe_unserialize(serialize(null))); + $this->assertFalse(util::maybe_unserialize(serialize(false))); + + $this->assertEquals( 'This is a string', util::maybe_unserialize( 'This is a string' ) ); + $this->assertEquals( 5.81, util::maybe_unserialize( 5.81 ) ); + $this->assertEquals( array(), util::maybe_unserialize( 'a:0:{}' ) ); + $this->assertEquals( $obj, util::maybe_unserialize( 'O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}' ) ); + $this->assertEquals( array( 'test', 'blah', 'hello' => 'world', 'array' => $obj ), util::maybe_unserialize( 'a:4:{i:0;s:4:"test";i:1;s:4:"blah";s:5:"hello";s:5:"world";s:5:"array";O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}}' ) ); + + // Test a broken serialization. + $expectedData = array( + 'Normal', + 'High-value Char: '.chr(231).'a-va?', // High-value Char: ça-va? [in ISO-8859-1] + ); + + $brokenSerialization = 'a:2:{i:0;s:6:"Normal";i:1;s:23:"High-value Char: ▒a-va?";}'; + + $unserializedData = util::maybe_unserialize($brokenSerialization); + $this->assertEquals($expectedData[0], $unserializedData[0], 'Did not properly fix the broken serialized data.'); + $this->assertEquals(substr($expectedData[1], 0, 10), substr($unserializedData[1], 0, 10), 'Did not properly fix the broken serialized data.'); + + // Test unfixable serialization. + $unfixableSerialization = 'a:2:{i:0;s:6:"Normal";}'; + $this->assertEquals($unfixableSerialization, util::maybe_unserialize($unfixableSerialization), 'Somehow the [previously?] impossible happened and utilphp thinks it has unserialized an unfixable serialization.'); + } + + public function test_is_serialized() + { + $this->assertFalse( util::is_serialized(1) ); + $this->assertFalse( util::is_serialized(null) ); + $this->assertFalse( util::is_serialized( 's:4:"test;' ) ); + $this->assertFalse( util::is_serialized( 'a:0:{}!' ) ); + $this->assertFalse( util::is_serialized( 'a:0' ) ); + $this->assertFalse( util::is_serialized( 'This is a string' ) ); + $this->assertFalse( util::is_serialized( 'a string' ) ); + $this->assertFalse( util::is_serialized( 'z:0;' ) ); + $this->assertTrue( util::is_serialized( 'N;' ) ); + $this->assertTrue( util::is_serialized( 'b:1;' ) ); + $this->assertTrue( util::is_serialized( 'a:0:{}' ) ); + $this->assertTrue( util::is_serialized( 'O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}' ) ); + } + + public function test_fix_broken_serialization() + { + $expectedData = array( + 'Normal', + 'High-value Char: '.chr(231).'a-va?', // High-value Char: ça-va? [in ISO-8859-1] + ); + + $brokenSerialization = 'a:2:{i:0;s:6:"Normal";i:1;s:23:"High-value Char: ▒a-va?";}'; + + // Temporarily override error handling to ensure that this is, in fact, [still] a broken serialization. + { + $expectedError = array( + 'errno' => 8, + 'errstr' => 'unserialize(): Error at offset 55 of 60 bytes' + ); + + $reportedError = array(); + set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) use (&$reportedError) { + $reportedError = compact('errno', 'errstr'); + }); + + unserialize($brokenSerialization); + + $this->assertEquals($expectedError['errno'], $reportedError['errno']); + // Because HHVM's unserialize() error message does not contain enough info to properly test. + if (!defined('HHVM_VERSION')) { + $this->assertEquals($expectedError['errstr'], $reportedError['errstr']); + } + restore_error_handler(); + } + + $fixedSerialization = util::fix_broken_serialization($brokenSerialization); + $unserializedData = unserialize($fixedSerialization); + $this->assertEquals($expectedData[0], $unserializedData[0], 'Did not properly fix the broken serialized data.'); + + $this->assertEquals(substr($expectedData[1], 0, 10), substr($unserializedData[1], 0, 10), 'Did not properly fix the broken serialized data.'); + } + + public function test_is_https() + { + $_SERVER['HTTPS'] = null; + + $this->assertFalse( util::is_https() ); + + $_SERVER['HTTPS'] = 'on'; + + $this->assertTrue( util::is_https() ); + } + + public function test_add_query_arg() + { + // Regular tests + $this->assertEquals( '/app/admin/users?user=5', util::add_query_arg( 'user', 5, '/app/admin/users' ) ); + $this->assertEquals( '/app/admin/users?user=5', util::add_query_arg( array( 'user' => 5 ), '/app/admin/users' ) ); + $this->assertEquals( '/app/admin/users?user=5', util::add_query_arg( array( 'user' => 5 ), null, '/app/admin/users' ) ); + $this->assertEquals( '/app/admin/users?action=edit&user=5', util::add_query_arg( 'user', 5, '/app/admin/users?action=edit' ) ); + $this->assertEquals( '/app/admin/users?action=edit&user=5', util::add_query_arg( array( 'user' => 5 ), '/app/admin/users?action=edit' ) ); + $this->assertEquals( '/app/admin/users?action=edit&tab=personal&user=5', util::add_query_arg( 'user', 5, '/app/admin/users?action=edit&tab=personal' ) ); + $this->assertEquals( '/app/admin/users?action=edit&tab=personal&user=5', util::add_query_arg( array( 'user' => 5 ), '/app/admin/users?action=edit&tab=personal' ) ); + + // Ensure strips false. + $this->assertEquals('/index.php', util::add_query_arg('debug', false, '/index.php')); + + // With a URL fragment + $this->assertEquals( '/app/admin/users?user=5#test', util::add_query_arg( 'user', 5, '/app/admin/users#test' ) ); + + // Full URL + $this->assertEquals( 'http://example.com/?a=b', util::add_query_arg( 'a', 'b', 'http://example.com' ) ); + + // Only the query string + $this->assertEquals( '?a=b&c=d', util::add_query_arg( 'c', 'd', '?a=b' ) ); + $this->assertEquals( 'a=b&c=d', util::add_query_arg( 'c', 'd', 'a=b' ) ); + + // Url encoding test + $this->assertEquals( '/app/admin/users?param=containsa%26sym', util::add_query_arg( 'param', 'containsa&sym', '/app/admin/users' ) ); + + // If not provided, grab the URI from the server. + $_SERVER['REQUEST_URI'] = '/app/admin/users'; + $this->assertEquals( '/app/admin/users?user=6', util::add_query_arg( array( 'user' => 6 ) ) ); + $this->assertEquals( '/app/admin/users?user=7', util::add_query_arg( 'user', 7 ) ); + } + + public function test_remove_query_arg() + { + $this->assertEquals( '/app/admin/users', util::remove_query_arg( 'user', '/app/admin/users?user=5' ) ); + $this->assertEquals( '/app/admin/users?action=edit', util::remove_query_arg( 'user', '/app/admin/users?action=edit&user=5' ) ); + $this->assertEquals( '/app/admin/users?user=5', util::remove_query_arg( array( 'tab', 'action' ), '/app/admin/users?action=edit&tab=personal&user=5' ) ); + } + + public function test_http_build_url() + { + $url = 'http://user:pass@example.com:8080/path/?query#fragment'; + + $expected = 'http://example.com/'; + $actual = util::http_build_url($url, array(), util::HTTP_URL_STRIP_ALL); + $this->assertEquals($expected, $actual); + + $expected = 'http://example.com:8080/path/?query#fragment'; + $actual = util::http_build_url($url, array(), util::HTTP_URL_STRIP_AUTH); + $this->assertEquals($expected, $actual); + + $this->assertEquals('https://dev.example.com/', util::http_build_url('http://example.com/', array('scheme' => 'https', 'host' => 'dev.example.com'))); + $this->assertEquals('http://example.com/#hi', util::http_build_url('http://example.com/', array('fragment' => 'hi'), util::HTTP_URL_REPLACE)); + $this->assertEquals('http://example.com/page', util::http_build_url('http://example.com/', array('path' => 'page'), util::HTTP_URL_JOIN_PATH)); + $this->assertEquals('http://example.com/page', util::http_build_url('http://example.com', array('path' => 'page'), util::HTTP_URL_JOIN_PATH)); + $this->assertEquals('http://example.com/?hi=Bro', util::http_build_url('http://example.com/', array('query' => 'hi=Bro'), util::HTTP_URL_JOIN_QUERY)); + $this->assertEquals('http://example.com/?show=1&hi=Bro', util::http_build_url('http://example.com/?show=1', array('query' => 'hi=Bro'), util::HTTP_URL_JOIN_QUERY)); + + $this->assertEquals('http://admin@example.com/', util::http_build_url('http://example.com/', array('user' => 'admin'))); + $this->assertEquals('http://admin:1@example.com/', util::http_build_url('http://example.com/', array('user' => 'admin', 'pass' => '1'))); + } + + public function test_str_to_bool() + { + $this->assertTrue( util::str_to_bool( 'true' ) ); + $this->assertTrue( util::str_to_bool( 'yes' ) ); + $this->assertTrue( util::str_to_bool( 'y' ) ); + $this->assertTrue( util::str_to_bool( 'oui' ) ); + $this->assertTrue( util::str_to_bool( 'vrai' ) ); + + $this->assertFalse( util::str_to_bool( 'false' ) ); + $this->assertFalse( util::str_to_bool( 'no' ) ); + $this->assertFalse( util::str_to_bool( 'n' ) ); + $this->assertFalse( util::str_to_bool( 'non' ) ); + $this->assertFalse( util::str_to_bool( 'faux' ) ); + + $this->assertFalse( util::str_to_bool( 'test' , false) ); + + } + + public function test_array_pluck() + { + $array = array( + array( + 'name' => 'Bob', + 'age' => 37 + ), + array( + 'name' => 'Fred', + 'age' => 37 + ), + array( + 'name' => 'Jane', + 'age' => 29 + ), + array( + 'name' => 'Brandon', + 'age' => 20 + ), + array( + 'age' => 41 + ) + ); + + $obj_array = array( + 'bob' => (object) array( + 'name' => 'Bob', + 'age' => 37 + ), + 'fred' => (object) array( + 'name' => 'Fred', + 'age' => 37 + ), + 'jane' => (object) array( + 'name' => 'Jane', + 'age' => 29 + ), + 'brandon' => (object) array( + 'name' => 'Brandon', + 'age' => 20 + ), + 'invalid' => (object) array( + 'age' => 41 + ) + ); + + $obj_array_expect = array( + 'bob' => 'Bob', + 'fred' => 'Fred', + 'jane' => 'Jane', + 'brandon' => 'Brandon' + ); + + $this->assertEquals( array( 'Bob', 'Fred', 'Jane', 'Brandon' ), util::array_pluck( $array, 'name' ) ); + $this->assertEquals( array( 'Bob', 'Fred', 'Jane', 'Brandon', array( 'age' => 41 ) ), util::array_pluck( $array, 'name', TRUE, FALSE ) ); + $this->assertEquals( $obj_array_expect, util::array_pluck( $obj_array, 'name' ) ); + $this->assertEquals( array( 'Bob', 'Fred', 'Jane', 'Brandon' ), util::array_pluck( $obj_array, 'name', FALSE ) ); + + $expected = array('Bob', 'Fred', 'Jane', 'Brandon', 'invalid' => (object)array('age' => 41)); + $this->assertEquals($expected, util::array_pluck($obj_array, 'name', FALSE, FALSE)); + $expected = array('Bob', 'Fred', 'Jane', 'Brandon', array('age' => 41)); + $this->assertEquals($expected, util::array_pluck($array, 'name', false, false)); + } + + public function test_htmlentities() + { + $this->assertEquals( 'One & Two', util::htmlentities( 'One & Two' ) ); + $this->assertEquals( 'One & Two', util::htmlentities( 'One & Two', TRUE ) ); + } + + public function test_htmlspecialchars() + { + $this->assertEquals( 'One & Two', util::htmlspecialchars( 'One & Two' ) ); + $this->assertEquals( 'One & Two', util::htmlspecialchars( 'One & Two', TRUE ) ); + } + + public function test_remove_accents() + { + $this->assertEquals( 'A', util::remove_accents( "\xC3\x81" ) ); + $this->assertEquals( 'e', util::remove_accents( "\xC4\x97" ) ); + $this->assertEquals( 'U', util::remove_accents( "\xC3\x9C" ) ); + $this->assertEquals( 'Ae', util::remove_accents( "Ä", 'de' ) ); + $this->assertEquals( 'OEoeAEDHTHssaedhth', util::remove_accents(chr(140) . chr(156) . chr(198) . chr(208) . chr(222) . chr(223) . chr(230) . chr(240) . chr(254))); + } + + public function test_zero_pad() + { + $this->assertEquals( '00000341', util::zero_pad( 341, 8 ) ); + $this->assertEquals( '341', util::zero_pad( 341, 1 ) ); + } + + public function test_human_time_diff() + { + $this->assertEquals( '1 second ago', util::human_time_diff( time() - 1 ) ); + $this->assertEquals( '30 seconds ago', util::human_time_diff( time() - 30 ) ); + $this->assertEquals( '1 minute ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MINUTE * 1.4 ) ) ); + $this->assertEquals( '5 minutes ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MINUTE * 5 ) ) ); + $this->assertEquals( '1 hour ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR ) ) ); + $this->assertEquals( '2 hours ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 2 ) ) ); + $this->assertEquals( '1 day ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 ) ) ); + $this->assertEquals( '5 days ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 * 5 ) ) ); + $this->assertEquals( '1 week ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 * 7 ) ) ); + $this->assertEquals( '2 weeks ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 * 14 ) ) ); + $this->assertEquals( '1 month ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_WEEK * 5 ) ) ); + $this->assertEquals( '2 months ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_WEEK * 10 ) ) ); + $this->assertEquals( '1 year ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MONTH * 15 ) ) ); + $this->assertEquals( '2 years ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MONTH * 36 ) ) ); + $this->assertEquals( '11 years ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MONTH * 140 ) ) ); + + $this->assertEquals( 'fifteen minutes ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MINUTE * 15 ), '', TRUE ) ); + } + + public function test_number_to_word() + { + try { + util::number_to_word('junk data'); + $this->fail('Accepted junk data'); + } catch(\LogicException $e) { + $this->assertEquals('Not a number', $e->getMessage()); + } + + // Partially numeric. + $this->assertEquals('', util::number_to_word('1a')); + + // Decimals + $this->assertEquals( 'five point zero five', util::number_to_word('5.05') ); + $this->assertEquals( 'zero point eight', util::number_to_word( 0.8 ) ); + + // Integers + $this->assertEquals( 'positive one', util::number_to_word( '+1' ) ); + $this->assertEquals( 'negative twelve', util::number_to_word( -12 ) ); + $this->assertEquals( 'one', util::number_to_word( 1 ) ); + $this->assertEquals( 'five', util::number_to_word( 5 ) ); + $this->assertEquals( 'fifteen', util::number_to_word( 15 ) ); + $this->assertEquals( 'twenty-one', util::number_to_word( 21 ) ); + $this->assertEquals( 'thirty-two', util::number_to_word( 32 ) ); + $this->assertEquals( 'forty-three', util::number_to_word( 43 ) ); + $this->assertEquals( 'fifty-four', util::number_to_word( 54 ) ); + $this->assertEquals( 'sixty-six', util::number_to_word( 66 ) ); + $this->assertEquals( 'seventy-seven', util::number_to_word( 77 ) ); + $this->assertEquals( 'eighty-eight', util::number_to_word( 88 ) ); + $this->assertEquals( 'ninety-nine', util::number_to_word( 99 ) ); + $this->assertEquals( 'one hundred and thirty-six', util::number_to_word( 136 ) ); + $this->assertEquals( 'ten', util::number_to_word( 10 ) ); + $this->assertEquals( 'twenty', util::number_to_word( 20 ) ); + $this->assertEquals( 'thirty', util::number_to_word( 30 ) ); + $this->assertEquals( 'forty', util::number_to_word( 40 ) ); + $this->assertEquals( 'fifty', util::number_to_word( 50 ) ); + $this->assertEquals( 'sixty', util::number_to_word( 60 ) ); + $this->assertEquals( 'seventy', util::number_to_word( 70 ) ); + $this->assertEquals( 'eighty', util::number_to_word( 80 ) ); + $this->assertEquals( 'ninety', util::number_to_word( 90 ) ); + $this->assertEquals( 'eleven', util::number_to_word( 11 ) ); + $this->assertEquals( 'thirteen', util::number_to_word( 13 ) ); + $this->assertEquals( 'fourteen', util::number_to_word( 14 ) ); + $this->assertEquals( 'fifteen', util::number_to_word( 15 ) ); + $this->assertEquals( 'sixteen', util::number_to_word( 16 ) ); + $this->assertEquals( 'seventeen', util::number_to_word( 17 ) ); + $this->assertEquals( 'eighteen', util::number_to_word( 18 ) ); + $this->assertEquals( 'nineteen', util::number_to_word( 19 ) ); + $this->assertEquals( 'one thousand', util::number_to_word( 1000 ) ); + $this->assertEquals( 'one million', util::number_to_word( 1000000 ) ); + $this->assertEquals( 'one billion', util::number_to_word( 1000000000 ) ); + $this->assertEquals( 'one trillion', util::number_to_word( 1000000000000 ) ); + $this->assertEquals( 'one quadrillion', util::number_to_word( '1000000000000000' ) ); + $this->assertEquals( 'one quintrillion', util::number_to_word( '1000000000000000000' ) ); + $this->assertEquals( 'one sextillion', util::number_to_word( '1000000000000000000000' ) ); + $this->assertEquals( 'one septillion', util::number_to_word( '1000000000000000000000000' ) ); + $this->assertEquals( 'one octillion', util::number_to_word( '1000000000000000000000000000' ) ); + $this->assertEquals( 'one nonillion', util::number_to_word( '1000000000000000000000000000000' ) ); + $this->assertEquals( 'one decillion', util::number_to_word( '1000000000000000000000000000000000' ) ); + $this->assertEquals( 'one', util::number_to_word( '1000000000000000000000000000000000000000000' ) ); + + } + + public function test_array_search_deep() + { + $users = array( + 1 => (object) array( 'username' => 'brandon', 'age' => 20 ), + 2 => (object) array( 'username' => 'matt', 'age' => 27 ), + 3 => (object) array( 'username' => 'jane', 'age' => 53 ), + 4 => (object) array( 'username' => 'john', 'age' => 41 ), + 5 => (object) array( 'username' => 'steve', 'age' => 11 ), + 6 => (object) array( 'username' => 'fred', 'age' => 42 ), + 7 => (object) array( 'username' => 'rasmus', 'age' => 21 ), + 8 => (object) array( 'username' => 'don', 'age' => 15 ), + 9 => array( 'username' => 'darcy', 'age' => 33 ), + ); + + $test = array( + 1 => 'brandon', + 2 => 'devon', + 3 => array( 'troy' ), + 4 => 'annie' + ); + + $this->assertFalse( util::array_search_deep( $test, 'bob' ) ); + $this->assertEquals( 3, util::array_search_deep( $test, 'troy' ) ); + $this->assertEquals( 4, util::array_search_deep( $test, 'annie' ) ); + $this->assertEquals( 2, util::array_search_deep( $test, 'devon', 'devon' ) ); + $this->assertEquals( 7, util::array_search_deep( $users, 'rasmus', 'username' ) ); + $this->assertEquals( 9, util::array_search_deep( $users, 'darcy', 'username' ) ); + $this->assertEquals( 1, util::array_search_deep( $users, 'brandon' ) ); + } + + public function test_array_map_deep() + { + $input = array( + '<', + 'abc', + '>', + 'def', + array( '&', 'test', '123' ), + (object) array( 'hey', '<>' ) + ); + + $expect = array( + '<', + 'abc', + '>', + 'def', + array( '&', 'test', '123' ), + (object) array( 'hey', '<>' ) + ); + + $this->assertEquals( $expect, util::array_map_deep( $input, 'htmlentities' ) ); + } + + public function test_random_string() + { + // Make sure the generated string contains only human friendly characters and is 30 characters long + $str = util::random_string( 30 ); + $this->assertTrue( (bool) preg_match( '/^([ABCDEFGHJKLMNPQRSTUVWXYZabcdefhjkmnprstuvwxyz23456789]{30})$/', $str ) ); + + // Make sure the generated string is 30 characters long + $str = util::random_string( 30, false, true ); + $this->assertTrue( strlen( $str ) === 30, 'random_string produced an invalid length string' ); + + // Make sure the generated string is 120 characters long + $str = util::random_string( 120 ); + $this->assertTrue(strlen( $str ) === 120, 'random_string produced an invalid length string'); + + // Make sure the string doesn't contain duplicate letters + $str = util::random_string( 53, true, false, true ); + $this->assertTrue(strlen($str) === 53, 'random_string produced an invalid length string'); + $this->assertTrue(count(array_unique(str_split($str))) === strlen($str), 'random_string produced a string with duplicate characters'); + + // Longer length than characters available + try { + $str = util::random_string( 55, true, false, true ); + $this->assertTrue( false ); + } catch (Exception $e) { + $this->assertTrue( true ); + } + + // Test secure variant + $str = util::secure_random_string(16); + $this->assertTrue(strlen($str) === 16); + + // Longer length than characters available + try { + $str = util::secure_random_string(0); + $this->assertTrue(false); + } catch (Exception $e) { + $this->assertTrue(true); + } + } + + public function test_match_string() + { + $this->assertTrue( util::match_string('a', 'a') ); + $this->assertFalse( util::match_string('a', ' a') ); + $this->assertFalse( util::match_string('/', '/something') ); + $this->assertTrue( util::match_string('test/*', 'test/first/second') ); + $this->assertTrue( util::match_string('*/test', 'first/second/test') ); + $this->assertFalse( util::match_string('first/', 'first/second/test') ); + $this->assertFalse( util::match_string('test', 'TEST') ); + $this->assertTrue( util::match_string('test', 'TEST', false) ); + } + + public function test_validate_email() + { + $this->assertTrue( util::validate_email( 'john.smith@gmail.com' ) ); + $this->assertTrue( util::validate_email( 'john.smith+label@gmail.com' ) ); + $this->assertTrue( util::validate_email( 'john.smith@gmail.co.uk' ) ); + } + + public function test_safe_truncate() + { + $this->assertEquals( 'The quick brown fox...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 24 ) ); + $this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 55 ) ); + $this->assertEquals( 'Th...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 2 ) ); + $this->assertEquals( 'The...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 3 ) ); + $this->assertEquals( 'The...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 7 ) ); + } + + public function test_limit_characters() + { + $this->assertEquals( 'The quick brown fox jump...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 24 ) ); + $this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 55 ) ); + $this->assertEquals( 'Th...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 2 ) ); + $this->assertEquals( 'The...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 3 ) ); + $this->assertEquals( 'The qui...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 7 ) ); + $this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 150 ) ); + } + + public function test_limit_words() + { + $this->assertEquals( 'The quick brown...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 3 ) ); + $this->assertEquals( 'The quick brown fox jumps...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 5 ) ); + $this->assertEquals( 'The...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 1 ) ); + $this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::limit_words( 'The quick brown fox jumps over the lazy dog', 90 ) ); + $this->assertEquals( 'The quick brown fox jumps over the...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 7 ) ); + } + + public function test_ordinal() + { + $this->assertEquals( '1st', util::ordinal( 1 ) ); + $this->assertEquals( '2nd', util::ordinal( 2 ) ); + $this->assertEquals( '3rd', util::ordinal( 3 ) ); + $this->assertEquals( '4th', util::ordinal( 4 ) ); + $this->assertEquals( '5th', util::ordinal( 5 ) ); + $this->assertEquals( '6th', util::ordinal( 6 ) ); + $this->assertEquals( '7th', util::ordinal( 7 ) ); + $this->assertEquals( '8th', util::ordinal( 8 ) ); + $this->assertEquals( '9th', util::ordinal( 9 ) ); + $this->assertEquals( '22nd', util::ordinal( 22 ) ); + $this->assertEquals( '23rd', util::ordinal( 23 ) ); + $this->assertEquals( '143rd', util::ordinal( 143 ) ); + } + + public function test_array_first() + { + $test = array( 'a' => array( 'a', 'b', 'c' ) ); + + $this->assertEquals( 'a', util::array_first( util::array_get( $test['a'] ) ) ); + } + + public function test_array_first_key() + { + $test = array( 'a' => array( 'a' => 'b', 'c' => 'd' ) ); + + $this->assertEquals( 'a', util::array_first_key( util::array_get( $test['a'] ) ) ); + } + + public function test_array_last() + { + $test = array( 'a' => array( 'a', 'b', 'c' ) ); + + $this->assertEquals( 'c', util::array_last( util::array_get( $test['a'] ) ) ); + } + + public function test_array_last_key() + { + $test = array( 'a' => array( 'a' => 'b', 'c' => 'd' ) ); + + $this->assertEquals( 'c', util::array_last_key( util::array_get( $test['a'] ) ) ); + } + + public function test_array_flatten() + { + $input = array( 'a', 'b', 'c', 'd', array( 'first' => 'e', 'f', 'second' => 'g', array( 'h', 'third' => 'i', array( array( array( array( 'j', 'k', 'l' ) ) ) ) ) ) ); + $expectNoKeys = range( 'a', 'l' ); + $expectWithKeys = array( + 'a', 'b', 'c', 'd', + 'first' => 'e', + 'f', + 'second' => 'g', + 'h', + 'third' => 'i', + 'j', 'k', 'l' + ); + + $this->assertEquals( $expectWithKeys, util::array_flatten( $input ) ); + $this->assertEquals( $expectNoKeys, util::array_flatten( $input, false ) ); + $this->assertEquals( $expectWithKeys, util::array_flatten( $input, true ) ); + } + + public function test_strip_space() + { + $input = ' The quick brown fox jumps over the lazy dog '; + $expect = 'Thequickbrownfoxjumpsoverthelazydog'; + + $this->assertEquals($expect, Util::strip_space($input)); + } + + public function test_sanitize_string() + { + $input = ' Benoit! à New-York? j’ai perçu 1 % : Qu’as-tu "gagné" chez M. V. Noël? Dix francs.'; + $expect = 'benoitanewyorkjaipercu1quastugagnechezmvnoeldixfrancs'; + + $this->assertEquals($expect, Util::sanitize_string($input)); + } + + public function test_get_gravatar() + { + $_SERVER['HTTPS'] = 'on'; + $this->assertEquals('https://secure.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=32', util::get_gravatar('john.doe@example.org')); + $this->assertEquals('https://secure.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=128', util::get_gravatar('john.doe@example.org', 128)); + + $_SERVER['HTTPS'] = 'off'; + $this->assertEquals('http://www.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=32', util::get_gravatar('john.doe@example.org')); + $this->assertEquals('http://www.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=128', util::get_gravatar('john.doe@example.org', 128)); + } + + public function test_get_client_ip() + { + $_SERVER['REMOTE_ADDR'] = '192.168.30.152'; + $_SERVER['HTTP_CLIENT_IP'] = '192.168.30.153'; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.30.154'; + $this->assertEquals('192.168.30.152', util::get_client_ip()); + $this->assertEquals('192.168.30.153', util::get_client_ip(true)); + + unset($_SERVER['HTTP_CLIENT_IP']); + $this->assertEquals('192.168.30.154', util::get_client_ip(true)); + unset($_SERVER['HTTP_X_FORWARDED_FOR']); + $this->assertEquals('192.168.30.152', util::get_client_ip(true)); + } + + public function test_full_permissions() + { + // Text a non-existant file. + $this->assertFalse(util::full_permissions('faker-123.blah'), 'Gave a permission value for a non-existant file.'); + + // Test an existing file. + $expected = '-rw-rw-rw-'; + $tempFile = tempnam(sys_get_temp_dir(), 'foo'); + $this->assertTrue(chmod($tempFile, 0666), 'Oops. Could not change temp file\'s permissions to 0666.'); + $this->assertEquals($expected, util::full_permissions($tempFile), 'Could not properly obtain permissions of an existing file.'); + unlink($tempFile); + + $this->assertEquals('lr--r--r--', util::full_permissions('fake-file-222', octdec('120444'))); + $this->assertEquals('ur--r--r--', util::full_permissions('fake-file-222', octdec('000444'))); + $this->assertEquals('srwxr-xr-x', util::full_permissions('fake-file-222', octdec('140755'))); + $this->assertEquals('drwxr-xr-x', util::full_permissions('fake-file-222', octdec('40755'))); + $this->assertEquals('brw-rw----', util::full_permissions('fake-file-222', octdec('60660'))); + $this->assertEquals('crw-rw----', util::full_permissions('fake-file-222', octdec('20660'))); + $this->assertEquals('prw-rw----', util::full_permissions('fake-file-222', octdec('10660'))); + $this->assertEquals('---x------', util::full_permissions('fake-file-222', octdec('100100'))); + $this->assertEquals('--w-------', util::full_permissions('fake-file-222', octdec('100200'))); + $this->assertEquals('--wx------', util::full_permissions('fake-file-222', octdec('100300'))); + $this->assertEquals('-r--------', util::full_permissions('fake-file-222', octdec('100400'))); + $this->assertEquals('-r-x------', util::full_permissions('fake-file-222', octdec('100500'))); + $this->assertEquals('-rw-------', util::full_permissions('fake-file-222', octdec('100600'))); + $this->assertEquals('-rwx------', util::full_permissions('fake-file-222', octdec('100700'))); + + // Windows does not have the concept of /. + if (!defined('PHP_WINDOWS_VERSION_MAJOR')) { + $this->assertEquals('drwxr-xr-x', util::full_permissions('/')); + } + } + + public function test_array_clean() + { + $input = array( 'a', 'b', '', null, false, 0); + $expect = array('a', 'b'); + $this->assertEquals($expect, Util::array_clean($input)); + } + + public function test_var_dump_plain() + { + $input = 'var'; + $expect = 'string(3) "var"'; + $this->assertEquals($expect, Util::var_dump_plain($input, true)); + + $input = true; + $expect = 'bool(true)'; + $this->assertEquals($expect, Util::var_dump_plain($input, true)); + + $input = 1; + $expect = 'int(1)'; + $this->assertEquals($expect, Util::var_dump_plain($input, true)); + + $input = 1.5; + $expect = 'float(1.5)'; + $this->assertEquals($expect, Util::var_dump_plain($input, true)); + + $input = null; + $expect = 'NULL'; + $this->assertEquals($expect, Util::var_dump_plain($input, true)); + + $input = fopen('php://memory', 'r'); + $expect = 'resource("stream") "' . $input . '"'; + $this->assertEquals($expect, Util::var_dump_plain($input, -1)); + fclose($input); + + // Test complex arrays. + $input = array(1, 2, 4, 6, 10 => 20, 100 => 200); + $actual = util::var_dump_plain($input, true); + $this->assertContains(')', $actual); + + // Test complex objects. + $experiment = new VarDumpExperiment(); + $actual = util::var_dump_plain($experiment, true); + $this->assertContains('1 => string(1', $actual); + } + + public function test_var_dump() + { + $input = 'var'; + $expect = '
string(3) "var"
'; + + // Ensure the proper output is returned + $this->assertEquals($expect, Util::var_dump($input, true)); + + // Ensure the proper output is actually outputted + $this->expectOutputString($expect); + util::var_dump($input); + + // Ensure we avoid infinite recursion on recursive arrays + $a = array('a' => 'value a', 'b' => 'value b'); + $b = array('test' => &$a); + $c = array('a' => &$a, 'b' => &$b); + $a['c'] = &$c; + $b['c'] = &$c; + $this->assertContains('*RECURSION DETECTED*', Util::var_dump($c, true)); + + // Ensure we avoid infinite recursion on recursive objects + $a = (object) array('a' => 'value a', 'b' => 'value b'); + $b = (object) array('test' => &$a); + $c = (object) array('a' => &$a, 'b' => &$b); + $a->c = &$c; + $b->c = &$c; + $this->assertContains('*RECURSION DETECTED*', Util::var_dump($c, true)); + + // Test class scoping. + $experiment = new VarDumpExperiment(); + $actual = util::var_dump($experiment, true); + + $snippet = substr($actual, strrpos($actual, 'display:inline')); + $this->assertContains('"public"', $snippet); + $this->assertContains('"protected:protected"', $snippet); + $this->assertContains('"private:VarDumpExperiment:private"', $actual); + } + + public function test_linkify() + { + $input = 'great websites: http://www.google.com?param=test and http://yahoo.com/a/nested/folder'; + $expect = 'great websites: http://www.google.com?param=test and http://yahoo.com/a/nested/folder'; + $this->assertEquals($expect, Util::linkify($input)); + + $this->assertEquals($expect, util::linkify($expect), 'linkify() tried to double linkify an href.'); + } + + public function test_start_with() + { + $this->assertTrue(Util::starts_with('start a string', 'start a')); + $this->assertFalse(Util::starts_with('start a string', 'string')); + } + + public function test_end_with() + { + $this->assertTrue(Util::ends_with('start a string', 'a string')); + $this->assertFalse(Util::ends_with('start a string', 'start')); + } + + public function test_contains() + { + $this->assertTrue(Util::str_contains('start a string', 'a string')); + $this->assertFalse(Util::str_contains('start a string', 'Start')); + } + + public function test_iContains() + { + $this->assertTrue(Util::str_icontains('start a string', 'a string')); + $this->assertTrue(Util::str_icontains('start a string', 'Start')); + } + + public function test_get_file_ext() + { + $input = 'a_pdf_fil.pdf'; + $expect = 'pdf'; + $this->assertEquals($expect, Util::get_file_ext($input)); + } + + public function test_rmdir() + { + $dirname = dirname(__FILE__); + + // Test deleting a non-existant directory + $this->assertFalse(file_exists($dirname . '/test1')); + $this->assertTrue(util::rmdir($dirname . '/test1')); + + // Test deleting an empty directory + $dir = $dirname . '/test2'; + mkdir($dir); + + $this->assertTrue(is_dir($dir)); + + if (is_dir($dir)) { + util::rmdir($dir); + $this->assertFalse(is_dir($dir)); + } + + // Test deleting a non-empty directory + $dir = $dirname . '/test3'; + $file = $dirname . '/test3/test.txt'; + mkdir($dir); + touch($file); + + $this->assertTrue(is_dir($dir)); + $this->assertTrue(is_file($file)); + + if (is_dir($dir)) { + util::rmdir($dir); + $this->assertFalse(is_dir($dir)); + $this->assertFalse(is_file($file)); + } + + // Test deleting a non-directory path + $file = $dirname . '/test4.txt'; + touch($file); + + try { + $str = util::rmdir($file); + $this->assertTrue(false); + } catch (\Exception $e) { + $this->assertTrue(true); + } + + unlink($file); + + // Test deleting a nested directory + $dir1 = $dirname . '/test5'; + $dir2 = $dirname . '/test5/nested_dir'; + $file1 = $dir1 . '/file1.txt'; + $file2 = $dir2 . '/file2.txt'; + mkdir($dir1); + mkdir($dir2); + touch($file1); + touch($file2); + + $this->assertTrue(is_dir($dir1)); + $this->assertTrue(is_dir($dir2)); + $this->assertTrue(is_file($file1)); + $this->assertTrue(is_file($file2)); + + if (is_dir($dir1)) { + util::rmdir($dir1); + $this->assertFalse(is_dir($dir1)); + $this->assertFalse(is_dir($dir2)); + $this->assertFalse(is_file($file1)); + $this->assertFalse(is_file($file2)); + } + + // Test symlink traversal. + $dir = $dirname . '/test6'; + $nestedDir = "$dir/nested"; + $symlink = "$dir/nested-symlink"; + + mkdir($dir); + mkdir($nestedDir); + + $symlinkStatus = symlink($nestedDir, $symlink); + $this->assertTrue($symlinkStatus, 'The test system does not support making symlinks.'); + + if (!$symlink) { + return; + } + + $this->assertTrue(util::rmdir($symlink, true), 'Could not delete a symlinked directory.'); + $this->assertFalse(file_exists($symlink), 'Could not delete a symlinked directory.'); + util::rmdir($dir, true); + $this->assertFalse(is_dir($dir), 'Could not delete a directory with a symlinked directory inside of it.'); + } + + public function test_get_current_url() + { + $expected = 'http://test.dev/test.php?foo=bar'; + $expectedAuth = 'http://admin:123@test.dev/test.php?foo=bar'; + $expectedPort = 'http://test.dev:443/test.php?foo=bar'; + $expectedPort2 = 'https://test.dev:80/test.php?foo=bar'; + $expectedSSL = 'https://test.dev/test.php?foo=bar'; + + $_SERVER['HTTP_HOST'] = 'test.dev'; + $_SERVER['SERVER_PORT'] = 80; + $_SERVER['REQUEST_URI'] = '/test.php?foo=bar'; + $_SERVER['QUERY_STRING'] = 'foo=bar'; + $_SERVER['PHP_SELF'] = '/test.php'; + + // Test regular. + $this->assertEquals($expected, util::get_current_url()); + + // Test server auth. + $_SERVER['PHP_AUTH_USER'] = 'admin'; + $_SERVER['PHP_AUTH_PW'] = '123'; + $this->assertEquals($expectedAuth, util::get_current_url()); + unset($_SERVER['PHP_AUTH_USER']); + unset($_SERVER['PHP_AUTH_PW']); + + // Test port. + $_SERVER['SERVER_PORT'] = 443; + $this->assertEquals($expectedPort, util::get_current_url()); + + // Test SSL. + $_SERVER['HTTPS'] = 'on'; + $this->assertEquals($expectedSSL, util::get_current_url()); + $_SERVER['SERVER_PORT'] = 80; + $this->assertEquals($expectedPort2, util::get_current_url()); + unset($_SERVER['HTTPS']); + + // Test no $_SERVER['REQUEST_URI'] (e.g., MS IIS). + unset($_SERVER['REQUEST_URI']); + $this->assertEquals($expected, util::get_current_url()); + } + + public function test_set_writable() + { + if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { + $this->markTestSkipped('This functionality is not working on Windows.'); + } + + if (posix_geteuid() === 0) { + $this->markTestSkipped('These tests don\'t work when run as root'); + } + + $this->assertFalse(util::set_writable('/no/such/file')); + + // Create a file to test with + $dirname = dirname(__FILE__); + $file = $dirname . '/test7'; + touch($file); + chmod($file, 0644); + + // The file is owned by us so it should be writable + $this->assertTrue(is_writable($file)); + $this->assertEquals('-rw-r--r--', util::full_permissions($file)); + + // Toggle writable bit off for us + util::set_writable($file, false); + clearstatcache(); + $this->assertFalse(is_writable($file)); + $this->assertEquals('-r--r--r--', util::full_permissions($file)); + + // Toggle writable bit back on for us + util::set_writable($file, true); + clearstatcache(); + $this->assertTrue(is_writable($file)); + $this->assertEquals('-rw-r--r--', util::full_permissions($file)); + + unlink($file); + } + + public function test_set_readable() + { + if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { + $this->markTestSkipped('This functionality is not working on Windows.'); + } + + if (posix_geteuid() === 0) { + $this->markTestSkipped('These tests don\'t work when run as root'); + } + + $this->assertFalse(util::set_readable('/no/such/file')); + + $dirname = dirname(__FILE__); + $file = $dirname . '/test8'; + touch($file); + + $this->assertTrue(is_readable($file)); + + util::set_readable($file, false); + clearstatcache(); + $this->assertFalse(is_readable($file)); + + util::set_readable($file, true); + clearstatcache(); + $this->assertTrue(is_readable($file)); + + unlink($file); + } + + public function test_set_executable() + { + if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { + $this->markTestSkipped('This functionality is not working on Windows.'); + } + + if (posix_geteuid() === 0) { + $this->markTestSkipped('These tests don\'t work when run as root'); + } + + $this->assertFalse(util::set_executable('/no/such/file')); + + $dirname = dirname(__FILE__); + $file = $dirname . '/test9'; + touch($file); + + $this->assertFalse(is_executable($file)); + + util::set_executable($file, true); + clearstatcache(); + $this->assertTrue(is_executable($file)); + + util::set_executable($file, false); + clearstatcache(); + $this->assertFalse(is_executable($file)); + + unlink($file); + } + + public function test_directory_size() { + $dirname = dirname(__FILE__); + $dir = $dirname .'/dir1'; + mkdir($dir); + $file1 = $dir .'/file1'; + file_put_contents($file1, '1234567890'); + $file2 = $dir .'/file2'; + file_put_contents($file2, range('a', 'z')); + $this->assertEquals(10 + 26, util::directory_size($dir)); + util::rmdir($dir); + } + + public function test_get_user_directory() { + // Test for OS Default. + $this->assertTrue(is_writable(util::get_user_directory())); + + $oldServer = $_SERVER; + unset($_SERVER); + // Test for UNIX. + $_SERVER['HOME'] = '/home/unknown'; + $this->assertEquals($_SERVER['HOME'], util::get_user_directory(), 'Could not get the user\'s home directory in UNIX.'); + unset($_SERVER); + + // Test for Windows. + $expected = 'X:\Users\ThisUser'; + $_SERVER['HOMEDRIVE'] = 'X:'; + $_SERVER['HOMEPATH'] = '\Users\ThisUser'; + $this->assertEquals($expected, util::get_user_directory(), 'Could not get the user\'s home directory in Windows.'); + + // In case the tests are not being run in isolation. + $_SERVER = $oldServer; + } + + public function test_directory_contents() { + $dirname = dirname(__FILE__); + $dir = $dirname . DIRECTORY_SEPARATOR .'dir1'; + mkdir($dir); + $file1 = $dir . DIRECTORY_SEPARATOR .'file1'; + touch($file1); + $this->assertEquals(array($file1), util::directory_contents($dir)); + util::rmdir($dir); + } +} diff --git a/f_config/DB.php b/f_config/DB.php index 156f53af..58d04ce8 100644 --- a/f_config/DB.php +++ b/f_config/DB.php @@ -9,4 +9,4 @@ if($SETTING->IsExist()) { Error('설정 파일이 없습니다. 설정을 먼저 하십시요!'); } -?> + diff --git a/f_config/DBS.php b/f_config/DBS.php index 9531d717..6f95263f 100644 --- a/f_config/DBS.php +++ b/f_config/DBS.php @@ -10,4 +10,4 @@ for($i=0; $i < $_serverCount; $i++) { } } -?> + diff --git a/f_config/MAIL.php b/f_config/MAIL.php index 63efdfce..9ababf2d 100644 --- a/f_config/MAIL.php +++ b/f_config/MAIL.php @@ -9,4 +9,4 @@ if($SETTING->IsExist()) { Error('설정 파일이 없습니다. 설정을 먼저 하십시요!'); } -?> + diff --git a/f_config/SESSION.php b/f_config/SESSION.php index d34cca64..2a50f81f 100644 --- a/f_config/SESSION.php +++ b/f_config/SESSION.php @@ -10,4 +10,4 @@ if($SESSION->IsLoggedIn() == false) { exit(1); } -?> + diff --git a/f_config/SETTING.php b/f_config/SETTING.php index ad29ba26..31d4665f 100644 --- a/f_config/SETTING.php +++ b/f_config/SETTING.php @@ -4,4 +4,4 @@ require_once(ROOT.W.F_FUNC.W.'class._Setting.php'); $SETTING = new _Setting(ROOT.W.D_SETTING.W.SET.PHP); -?> + diff --git a/f_config/SETTINGS.php b/f_config/SETTINGS.php index cb2e988a..f1e91f30 100644 --- a/f_config/SETTINGS.php +++ b/f_config/SETTINGS.php @@ -8,4 +8,4 @@ foreach($_serverDirs as $serverDir) { $i++; } -?> + diff --git a/f_config/_common.php b/f_config/_common.php index cea1c49d..b25b4786 100644 --- a/f_config/_common.php +++ b/f_config/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/f_config/app.php b/f_config/app.php index 7900672c..25a61033 100644 --- a/f_config/app.php +++ b/f_config/app.php @@ -42,4 +42,4 @@ $_serverLevels = array( 1 ); -?> + diff --git a/f_config/config.php b/f_config/config.php index 03dd7eac..e6133c67 100644 --- a/f_config/config.php +++ b/f_config/config.php @@ -53,4 +53,4 @@ define('SLEEP', 'sleep'); //define(BLOCKBODY, ''); define('BLOCKBODY', 'oncontextmenu="return false" onselectstart="return false" ondragstart="return false"'); -?> + diff --git a/f_func/_common.php b/f_func/_common.php index cea1c49d..b25b4786 100644 --- a/f_func/_common.php +++ b/f_func/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/f_func/class._Chat.php b/f_func/class._Chat.php index 85f5d064..1ada9fc6 100644 --- a/f_func/class._Chat.php +++ b/f_func/class._Chat.php @@ -24,4 +24,4 @@ class _Chat { } } -?> + diff --git a/f_func/class._DB.php b/f_func/class._DB.php index 8ba7d4cf..3b7bc593 100644 --- a/f_func/class._DB.php +++ b/f_func/class._DB.php @@ -142,4 +142,4 @@ class _DB { } } -?> + diff --git a/f_func/class._JSON.php b/f_func/class._JSON.php index 2f3641a0..d34c2018 100644 --- a/f_func/class._JSON.php +++ b/f_func/class._JSON.php @@ -52,4 +52,4 @@ class _JSON { } } -?> + diff --git a/f_func/class._Lock.php b/f_func/class._Lock.php index 5dcf8cfa..ac6e5bc4 100644 --- a/f_func/class._Lock.php +++ b/f_func/class._Lock.php @@ -70,4 +70,4 @@ class _Lock { } } -?> + diff --git a/f_func/class._Log.php b/f_func/class._Log.php index c7c88759..6c3b8bec 100644 --- a/f_func/class._Log.php +++ b/f_func/class._Log.php @@ -45,4 +45,4 @@ class _Log { } } -?> + diff --git a/f_func/class._Mail.php b/f_func/class._Mail.php index 3199a606..9d218d20 100644 --- a/f_func/class._Mail.php +++ b/f_func/class._Mail.php @@ -37,4 +37,4 @@ class _Mail { } } -?> + diff --git a/f_func/class._Process.php b/f_func/class._Process.php index 0d5e6b33..035845a5 100644 --- a/f_func/class._Process.php +++ b/f_func/class._Process.php @@ -33,4 +33,4 @@ class _Process { } } -?> + diff --git a/f_func/class._Queue.php b/f_func/class._Queue.php index 87f9000e..6d04a335 100644 --- a/f_func/class._Queue.php +++ b/f_func/class._Queue.php @@ -39,4 +39,4 @@ class _Queue { return $value; } } -?> + diff --git a/f_func/class._Session.php b/f_func/class._Session.php index a96c4d0b..c9c8df9e 100644 --- a/f_func/class._Session.php +++ b/f_func/class._Session.php @@ -72,4 +72,4 @@ class _Session { } } -?> + diff --git a/f_func/class._Setting.php b/f_func/class._Setting.php index afc0c0eb..5cf3d1ce 100644 --- a/f_func/class._Setting.php +++ b/f_func/class._Setting.php @@ -78,4 +78,4 @@ class _Setting { } } -?> + diff --git a/f_func/class._String.php b/f_func/class._String.php index 6a161790..5ab0cbb6 100644 --- a/f_func/class._String.php +++ b/f_func/class._String.php @@ -234,4 +234,3 @@ class _String { } } -?> diff --git a/f_func/class._Time.php b/f_func/class._Time.php index 9f3c7cf8..cc72e34a 100644 --- a/f_func/class._Time.php +++ b/f_func/class._Time.php @@ -44,4 +44,4 @@ class _Time { } } -?> + diff --git a/f_func/class._Validation.php b/f_func/class._Validation.php index 62ee8d1e..dbf4e7da 100644 --- a/f_func/class._Validation.php +++ b/f_func/class._Validation.php @@ -111,4 +111,4 @@ class _Validation { } } -?> + diff --git a/f_func/func.php b/f_func/func.php index deded7cb..4d8a4377 100644 --- a/f_func/func.php +++ b/f_func/func.php @@ -97,4 +97,4 @@ function delExpiredInDir($dir, $t) { return $success; } -?> + diff --git a/f_install/_common.php b/f_install/_common.php index cea1c49d..b25b4786 100644 --- a/f_install/_common.php +++ b/f_install/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/f_install/install1Post.php b/f_install/install1Post.php index b6772741..f025ec74 100644 --- a/f_install/install1Post.php +++ b/f_install/install1Post.php @@ -49,10 +49,12 @@ foreach($querys as $query) { // 파일로 DB 정보 저장 $file = @fopen(ROOT.W.D_SETTING.W.SET.PHP, 'w') or ErrorToScreen('설정 실패. 디렉토리의 퍼미션을 707로 주십시요'); -@fwrite($file, "\n") or ErrorToScreen('설정 실패. 디렉토리의 퍼미션을 707로 주십시요'); +@fwrite($file, " - + +Go to install2.php
+Todo : Back to replace code diff --git a/f_retrival/_common.php b/f_retrival/_common.php index bc36bd5c..9ed1eefa 100644 --- a/f_retrival/_common.php +++ b/f_retrival/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_banner/banner.php b/i_banner/banner.php index 78dc7a6c..5f8da1ca 100644 --- a/i_banner/banner.php +++ b/i_banner/banner.php @@ -54,4 +54,3 @@ switch(rand()%10) { break; } */ -?> diff --git a/i_entrance/_common.php b/i_entrance/_common.php index d56bd857..f57670c9 100644 --- a/i_entrance/_common.php +++ b/i_entrance/_common.php @@ -8,4 +8,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_entrance/adminPost.php b/i_entrance/adminPost.php index c176fe6a..14b36414 100644 --- a/i_entrance/adminPost.php +++ b/i_entrance/adminPost.php @@ -6,6 +6,7 @@ // $_POST['select'] : 0: 폐쇄, 1: 리셋, 2: 오픈 require_once('_common.php'); +require_once(ROOT.W.E_LIB.W.'util.php'); require_once(ROOT.W.F_FUNC.W.'class._JSON.php'); require_once(ROOT.W.F_CONFIG.W.DB.PHP); require_once(ROOT.W.F_CONFIG.W.SESSION.PHP); @@ -23,10 +24,10 @@ function getPost($str){ return $temp; } -$action = getPost('action'); -$notice = getPost('notice'); -$server = getPost('server'); -$select = getPost('select'); +$action = util::array_get($_POST['action'], ''); +$notice = util::array_get($_POST['notice'], ''); +$server = util::array_get($_POST['server'], ''); +$select = util::array_get($_POST['select'], ''); $rs = $DB->Select('GRADE', 'MEMBER', "NO='{$SESSION->NoMember()}'"); @@ -48,7 +49,10 @@ if($member['GRADE'] < 6) { rename(ROOT.W.$serverDir.'_rest', ROOT.W.$serverDir); $response['result'] = 'SUCCESS'; } elseif($select == 1) { - @unlink(ROOT.W.$serverDir.'_close'.W.D_SETTING.W.SET.PHP); + if(file_exists(ROOT.W.$serverDir.'_close'.W.D_SETTING.W.SET.PHP)){ + @unlink(ROOT.W.$serverDir.'_close'.W.D_SETTING.W.SET.PHP); + } + $response['installURL'] = ROOT.W."{$serverDir}_close/install.php"; $response['result'] = 'SUCCESS'; } elseif($select == 2) { @@ -64,5 +68,3 @@ if($member['GRADE'] < 6) { sleep(1); echo json_encode($response); - -?> diff --git a/i_entrance/donation/Get.php b/i_entrance/donation/Get.php index 24e3d354..629556b8 100644 --- a/i_entrance/donation/Get.php +++ b/i_entrance/donation/Get.php @@ -42,4 +42,4 @@ if($member['GRADE'] < 6) { sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/donation/Post.php b/i_entrance/donation/Post.php index c0cae029..7a4293cd 100644 --- a/i_entrance/donation/Post.php +++ b/i_entrance/donation/Post.php @@ -55,4 +55,4 @@ if($member['GRADE'] < 6) { echo json_encode($response); -?> + diff --git a/i_entrance/donation/_common.php b/i_entrance/donation/_common.php index 90e4756f..d7a78a7b 100644 --- a/i_entrance/donation/_common.php +++ b/i_entrance/donation/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_entrance/donation/calculatePost.php b/i_entrance/donation/calculatePost.php index f413ccd6..2970d44e 100644 --- a/i_entrance/donation/calculatePost.php +++ b/i_entrance/donation/calculatePost.php @@ -43,4 +43,4 @@ if($member['GRADE'] < 6) { echo json_encode($response); -?> + diff --git a/i_entrance/enterPost.php b/i_entrance/enterPost.php index 550878f4..10e785b4 100644 --- a/i_entrance/enterPost.php +++ b/i_entrance/enterPost.php @@ -19,5 +19,3 @@ $response['result'] = 'SUCCESS'; sleep(1); echo json_encode($response); - -?> diff --git a/i_entrance/logoutPost.php b/i_entrance/logoutPost.php index 5d9a5bf6..990d48c8 100644 --- a/i_entrance/logoutPost.php +++ b/i_entrance/logoutPost.php @@ -13,4 +13,4 @@ $response['result'] = 'SUCCESS'; sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/manage/Get.php b/i_entrance/manage/Get.php index 41d73e00..104ae490 100644 --- a/i_entrance/manage/Get.php +++ b/i_entrance/manage/Get.php @@ -75,4 +75,4 @@ $response['result'] = 'SUCCESS'; sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/manage/_common.php b/i_entrance/manage/_common.php index 90e4756f..d7a78a7b 100644 --- a/i_entrance/manage/_common.php +++ b/i_entrance/manage/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_entrance/manage/deletePost.php b/i_entrance/manage/deletePost.php index f810ef4f..aa08f78c 100644 --- a/i_entrance/manage/deletePost.php +++ b/i_entrance/manage/deletePost.php @@ -44,4 +44,4 @@ if($dt == $rf) { sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/manage/iconPost.php b/i_entrance/manage/iconPost.php index 623eaa69..a77e3e20 100644 --- a/i_entrance/manage/iconPost.php +++ b/i_entrance/manage/iconPost.php @@ -76,4 +76,4 @@ echo ""; -?> + diff --git a/i_entrance/manage/passwordPost.php b/i_entrance/manage/passwordPost.php index f9d2be5f..b0715c75 100644 --- a/i_entrance/manage/passwordPost.php +++ b/i_entrance/manage/passwordPost.php @@ -36,4 +36,4 @@ if($member['PW'] != $pw) { sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/manage/quitPost.php b/i_entrance/manage/quitPost.php index 1410fb92..d3e1f51f 100644 --- a/i_entrance/manage/quitPost.php +++ b/i_entrance/manage/quitPost.php @@ -33,4 +33,4 @@ if($member['PW'] != $pw) { sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/member/Get.php b/i_entrance/member/Get.php index dac7382c..be0b8477 100644 --- a/i_entrance/member/Get.php +++ b/i_entrance/member/Get.php @@ -87,4 +87,4 @@ if($member['GRADE'] < 6) { sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/member/Post.php b/i_entrance/member/Post.php index 55a1b047..5f751122 100644 --- a/i_entrance/member/Post.php +++ b/i_entrance/member/Post.php @@ -118,4 +118,4 @@ if($member['GRADE'] < 6) { sleep(1); echo json_encode($response); -?> + diff --git a/i_entrance/member/_common.php b/i_entrance/member/_common.php index 90e4756f..d7a78a7b 100644 --- a/i_entrance/member/_common.php +++ b/i_entrance/member/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_entrance/serverListPost.php b/i_entrance/serverListPost.php index f48df28d..f6d8f2a3 100644 --- a/i_entrance/serverListPost.php +++ b/i_entrance/serverListPost.php @@ -150,5 +150,5 @@ function getTurnTerm($term) { return $str; } -?> + diff --git a/i_login/Post.php b/i_login/Post.php index b6575890..6043d352 100644 --- a/i_login/Post.php +++ b/i_login/Post.php @@ -51,4 +51,4 @@ if($DB->Count($rs) == 1) { sleep(1); echo json_encode($response); -?> + diff --git a/i_login/_common.php b/i_login/_common.php index cea1c49d..b25b4786 100644 --- a/i_login/_common.php +++ b/i_login/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_login/findpw/Get.php b/i_login/findpw/Get.php index 56fc291d..4f3cb3e5 100644 --- a/i_login/findpw/Get.php +++ b/i_login/findpw/Get.php @@ -12,4 +12,4 @@ $response['result'] = 'SUCCESS'; sleep(1); echo json_encode($response); -?> + diff --git a/i_login/findpw/Post.php b/i_login/findpw/Post.php index e771b808..9e80a86e 100644 --- a/i_login/findpw/Post.php +++ b/i_login/findpw/Post.php @@ -120,4 +120,4 @@ $response['msg'] = "정상적으로 비번이 변경되었습니다. ID: {$id}"; sleep(1); echo json_encode($response); -?> + diff --git a/i_login/findpw/_common.php b/i_login/findpw/_common.php index 90e4756f..d7a78a7b 100644 --- a/i_login/findpw/_common.php +++ b/i_login/findpw/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_login/findpw/checkPost.php b/i_login/findpw/checkPost.php index b2be62b9..630abcb1 100644 --- a/i_login/findpw/checkPost.php +++ b/i_login/findpw/checkPost.php @@ -82,4 +82,4 @@ if($type == 0) { sleep(1); echo json_encode($response); -?> + diff --git a/i_login/findpw/sendCodePost.php b/i_login/findpw/sendCodePost.php index 96878d95..e062ef40 100644 --- a/i_login/findpw/sendCodePost.php +++ b/i_login/findpw/sendCodePost.php @@ -46,4 +46,4 @@ if($err == 1) { //sleep(1); echo json_encode($response); -?> + diff --git a/i_login/findpw/verifyCodePost.php b/i_login/findpw/verifyCodePost.php index f704f9b6..9926eaa9 100644 --- a/i_login/findpw/verifyCodePost.php +++ b/i_login/findpw/verifyCodePost.php @@ -45,4 +45,4 @@ if($err == 1) { sleep(1); echo json_encode($response); -?> + diff --git a/i_login/join/Get.php b/i_login/join/Get.php index 56fc291d..4f3cb3e5 100644 --- a/i_login/join/Get.php +++ b/i_login/join/Get.php @@ -12,4 +12,4 @@ $response['result'] = 'SUCCESS'; sleep(1); echo json_encode($response); -?> + diff --git a/i_login/join/_common.php b/i_login/join/_common.php index 90e4756f..d7a78a7b 100644 --- a/i_login/join/_common.php +++ b/i_login/join/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_login/join/sendCodePost.php b/i_login/join/sendCodePost.php index 31f1526f..5c74adfe 100644 --- a/i_login/join/sendCodePost.php +++ b/i_login/join/sendCodePost.php @@ -46,4 +46,4 @@ if($err == 1) { //sleep(1); echo json_encode($response); -?> + diff --git a/i_login/join/verifyCodePost.php b/i_login/join/verifyCodePost.php index f704f9b6..9926eaa9 100644 --- a/i_login/join/verifyCodePost.php +++ b/i_login/join/verifyCodePost.php @@ -45,4 +45,4 @@ if($err == 1) { sleep(1); echo json_encode($response); -?> + diff --git a/i_other/_common.php b/i_other/_common.php index cea1c49d..b25b4786 100644 --- a/i_other/_common.php +++ b/i_other/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/i_popup/_common.php b/i_popup/_common.php index cea1c49d..b25b4786 100644 --- a/i_popup/_common.php +++ b/i_popup/_common.php @@ -7,4 +7,4 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> + diff --git a/install.php b/install.php index c364afb1..09e0de36 100644 --- a/install.php +++ b/install.php @@ -3,4 +3,6 @@ require_once('_common.php'); ?> - + +Go to f_install/install.php
+Todo : Back to replace code diff --git a/twe_close/MYDB.php b/twe_close/MYDB.php index fff8a763..708a2533 100644 --- a/twe_close/MYDB.php +++ b/twe_close/MYDB.php @@ -38,4 +38,3 @@ function MYDB_close($connect) { return mysqli_close($connect); } -?> diff --git a/twe_close/_119_b.php b/twe_close/_119_b.php index 2f3b9668..9f3d1eb9 100644 --- a/twe_close/_119_b.php +++ b/twe_close/_119_b.php @@ -53,5 +53,5 @@ case "락풀기": break; } -echo ""; -?> +//echo ""; +echo '_119.php';//TODO:replace diff --git a/twe_close/_admin1_submit.php b/twe_close/_admin1_submit.php index 3f3bd5b2..1e0f67c0 100644 --- a/twe_close/_admin1_submit.php +++ b/twe_close/_admin1_submit.php @@ -175,6 +175,6 @@ switch($btn) { break; } -echo ""; -?> +//echo ""; +echo '_admin1.php';//TODO:replace diff --git a/twe_close/_admin2_submit.php b/twe_close/_admin2_submit.php index 295d675e..37c04f3f 100644 --- a/twe_close/_admin2_submit.php +++ b/twe_close/_admin2_submit.php @@ -427,6 +427,6 @@ switch($btn) { break; } -echo ""; -?> +//echo ""; +echo '_admin2.php';//TODO:replace diff --git a/twe_close/_admin3_submit.php b/twe_close/_admin3_submit.php index 60ed41b5..10a09171 100644 --- a/twe_close/_admin3_submit.php +++ b/twe_close/_admin3_submit.php @@ -129,6 +129,6 @@ switch($btn) { break; } -echo ""; -?> +//echo ""; +echo '_admin3.php';//TODO:replace diff --git a/twe_close/_admin4_submit.php b/twe_close/_admin4_submit.php index 344f7def..b9cd07b5 100644 --- a/twe_close/_admin4_submit.php +++ b/twe_close/_admin4_submit.php @@ -102,6 +102,6 @@ switch($btn) { break; } -echo ""; -?> +//echo ""; +echo '_admin4.php'; //TODO:replace diff --git a/twe_close/_admin5_submit.php b/twe_close/_admin5_submit.php index 3a6bcb98..129ad500 100644 --- a/twe_close/_admin5_submit.php +++ b/twe_close/_admin5_submit.php @@ -25,6 +25,7 @@ switch($btn) { break; } -echo ""; -?> +//echo ""; +echo '_admin5.php';//TODO:replace + diff --git a/twe_close/_simul.php b/twe_close/_simul.php index b993bd97..5f3b4120 100644 --- a/twe_close/_simul.php +++ b/twe_close/_simul.php @@ -1559,4 +1559,4 @@ function printSimul($game, $i) { "; } -?> + diff --git a/twe_close/a_traffic.php b/twe_close/a_traffic.php index 3731917b..ac80e299 100644 --- a/twe_close/a_traffic.php +++ b/twe_close/a_traffic.php @@ -254,4 +254,4 @@ function getHexCode($hex) { case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F"; } } -?> + diff --git a/twe_close/a_vote.php b/twe_close/a_vote.php index b6acb56c..9af23490 100644 --- a/twe_close/a_vote.php +++ b/twe_close/a_vote.php @@ -335,4 +335,4 @@ function getNewColor($type) { return $color; } -?> + diff --git a/twe_close/analytics.php b/twe_close/analytics.php index bf3f0d19..f0e83ec9 100644 --- a/twe_close/analytics.php +++ b/twe_close/analytics.php @@ -1,4 +1,4 @@ - + +b_betting.php diff --git a/twe_close/c_chiefboard.php b/twe_close/c_chiefboard.php index 2f0fa578..00e01c6b 100644 --- a/twe_close/c_chiefboard.php +++ b/twe_close/c_chiefboard.php @@ -42,8 +42,8 @@ if(CheckBlock($connect) != 1 && CheckBlock($connect) != 3) { } } -echo ""; - +//echo ""; +echo 'b_chiefboard.php';//TODO:replace ?> diff --git a/twe_close/c_dipcenter.php b/twe_close/c_dipcenter.php index 65334296..4cf79a5c 100644 --- a/twe_close/c_dipcenter.php +++ b/twe_close/c_dipcenter.php @@ -56,7 +56,7 @@ if($btn == "국가방침") { MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); } -echo ""; +//echo ""; +echo 'b_dipcenter.php';//TODO:replace -?> diff --git a/twe_close/c_double.php b/twe_close/c_double.php index 8c99759b..8a000e70 100644 --- a/twe_close/c_double.php +++ b/twe_close/c_double.php @@ -124,5 +124,4 @@ if($command == 46) { echo ""; } -?> diff --git a/twe_close/c_msgsubmit.php b/twe_close/c_msgsubmit.php index 4a0eba39..2cfcd684 100644 --- a/twe_close/c_msgsubmit.php +++ b/twe_close/c_msgsubmit.php @@ -113,7 +113,6 @@ if($genlist == 9999 && str_replace(" ", "", $msg) != "") { fclose($fp); } -echo ""; - -?> +//echo ""; +echo 'msglist.php';//TODO:replace diff --git a/twe_close/c_myBossInfo.php b/twe_close/c_myBossInfo.php index f12bee51..7b96765c 100644 --- a/twe_close/c_myBossInfo.php +++ b/twe_close/c_myBossInfo.php @@ -250,7 +250,7 @@ if($btn == "추방") { } } -echo ""; +//echo ""; +echo 'b_myBossInfo.php'//TODO:replace -?> diff --git a/twe_close/c_nationboard.php b/twe_close/c_nationboard.php index 6d3544d3..78e31361 100644 --- a/twe_close/c_nationboard.php +++ b/twe_close/c_nationboard.php @@ -42,7 +42,8 @@ if(CheckBlock($connect) != 1 && CheckBlock($connect) != 3) { } } -echo ""; +//echo ""; +echo 'b_nationboard.php';//TODO:replace ?> diff --git a/twe_close/c_nationrule.php b/twe_close/c_nationrule.php index 9744f007..08563c1a 100644 --- a/twe_close/c_nationrule.php +++ b/twe_close/c_nationrule.php @@ -16,7 +16,6 @@ $msg = addslashes(SQ2DQ($msg)); $query = "update nation set rule='$msg' where nation='$me[nation]'"; MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); -echo ""; - -?> +//echo ""; +echo 'b_nationrule.php';//TODO:replace diff --git a/twe_close/c_tournament.php b/twe_close/c_tournament.php index 157dc74a..666531a9 100644 --- a/twe_close/c_tournament.php +++ b/twe_close/c_tournament.php @@ -202,4 +202,5 @@ if($btn == "자동개최설정" && $me[userlevel] >= 5) { } ?> - + +b_tournament.php diff --git a/twe_close/c_troop.php b/twe_close/c_troop.php index 5dbdfb79..0da27a5f 100644 --- a/twe_close/c_troop.php +++ b/twe_close/c_troop.php @@ -54,5 +54,3 @@ if($btn == "부 대 창 설" && $name != "" && $me[troop] == 0) { echo ""; MYDB_close($connect); -?> - diff --git a/twe_close/c_vacation.php b/twe_close/c_vacation.php index b4062169..8101f999 100644 --- a/twe_close/c_vacation.php +++ b/twe_close/c_vacation.php @@ -14,7 +14,6 @@ $admin[killturn] *= 3; $query = "update general set killturn='$admin[killturn]' where user_id='$_SESSION[p_id]'"; $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); -echo ""; - -?> +//echo ""; +echo 'b_myPage.php'; //TODO:replace diff --git a/twe_close/c_vote.php b/twe_close/c_vote.php index c9e0d242..67798485 100644 --- a/twe_close/c_vote.php +++ b/twe_close/c_vote.php @@ -73,4 +73,5 @@ if($btn == "수정" && $me[userlevel] >= 5) { } ?> - + +a_vote.php diff --git a/twe_close/d_ally.php b/twe_close/d_ally.php index 3e6b36f4..21c29d87 100644 --- a/twe_close/d_ally.php +++ b/twe_close/d_ally.php @@ -116,5 +116,3 @@ pushGenLog($you, $youlog); echo ""; -?> - diff --git a/twe_close/d_cancel.php b/twe_close/d_cancel.php index 94281351..7dd03327 100644 --- a/twe_close/d_cancel.php +++ b/twe_close/d_cancel.php @@ -95,5 +95,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/twe_close/d_cease.php b/twe_close/d_cease.php index 76c125f7..88dfd30c 100644 --- a/twe_close/d_cease.php +++ b/twe_close/d_cease.php @@ -100,5 +100,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/twe_close/d_merge.php b/twe_close/d_merge.php index d57c213e..9a202e95 100644 --- a/twe_close/d_merge.php +++ b/twe_close/d_merge.php @@ -134,5 +134,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/twe_close/d_scout.php b/twe_close/d_scout.php index 9900e98f..934a0503 100644 --- a/twe_close/d_scout.php +++ b/twe_close/d_scout.php @@ -160,5 +160,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/twe_close/d_setting/_common.php b/twe_close/d_setting/_common.php index 90e4756f..57949e8d 100644 --- a/twe_close/d_setting/_common.php +++ b/twe_close/d_setting/_common.php @@ -7,4 +7,3 @@ require_once(ROOT.W.F_CONFIG.W.APP.PHP); require_once(ROOT.W.F_FUNC.W.FUNC.PHP); CustomHeader(); -?> diff --git a/twe_close/d_surrender.php b/twe_close/d_surrender.php index 729fe7fa..799f448a 100644 --- a/twe_close/d_surrender.php +++ b/twe_close/d_surrender.php @@ -124,5 +124,3 @@ pushHistory($connect, $history); echo ""; -?> - diff --git a/twe_close/data/connected.php b/twe_close/data/connected.php index caaabefa..de11d5cd 100644 --- a/twe_close/data/connected.php +++ b/twe_close/data/connected.php @@ -1 +1 @@ - + - diff --git a/twe_close/event_2.php b/twe_close/event_2.php index 94bcc518..b104b92b 100644 --- a/twe_close/event_2.php +++ b/twe_close/event_2.php @@ -253,5 +253,3 @@ function RegGeneral3($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> - diff --git a/twe_close/event_3.php b/twe_close/event_3.php index 48fd3d51..a613f347 100644 --- a/twe_close/event_3.php +++ b/twe_close/event_3.php @@ -114,5 +114,3 @@ function RegGeneral3($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> - diff --git a/twe_close/event_4.php b/twe_close/event_4.php index 9d3b1c10..0b4ec99d 100644 --- a/twe_close/event_4.php +++ b/twe_close/event_4.php @@ -143,5 +143,3 @@ function RegGeneral4($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> - diff --git a/twe_close/func.php b/twe_close/func.php index 31577742..7ef2380e 100644 --- a/twe_close/func.php +++ b/twe_close/func.php @@ -7416,4 +7416,3 @@ function Submit($url, $msg="", $msg2="") { "; } -?> diff --git a/twe_close/func_auction.php b/twe_close/func_auction.php index 9ffd729c..065d6919 100644 --- a/twe_close/func_auction.php +++ b/twe_close/func_auction.php @@ -345,4 +345,3 @@ function processAuction($connect) { MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/twe_close/func_history.php b/twe_close/func_history.php index bd18360c..210eca7c 100644 --- a/twe_close/func_history.php +++ b/twe_close/func_history.php @@ -128,4 +128,3 @@ function LogHistory($connect, $isFirst=0) { if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', LogHistory Finish'); return true; } -?> diff --git a/twe_close/func_http.php b/twe_close/func_http.php index 09dd69d3..c809b579 100644 --- a/twe_close/func_http.php +++ b/twe_close/func_http.php @@ -285,4 +285,3 @@ class HTTP{ } } } -?> \ No newline at end of file diff --git a/twe_close/func_npc.php b/twe_close/func_npc.php index 9c8f7d1d..c1444023 100644 --- a/twe_close/func_npc.php +++ b/twe_close/func_npc.php @@ -1861,4 +1861,3 @@ function RiceBillRate($connect, $nation, $rate, $rice_rate, $type, $rice) { MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/twe_close/func_process.php b/twe_close/func_process.php index b75f7a2b..9e9d6a43 100644 --- a/twe_close/func_process.php +++ b/twe_close/func_process.php @@ -6145,4 +6145,3 @@ function process_99($connect, &$general) { pushGenLog($general, $log); } -?> diff --git a/twe_close/func_string.php b/twe_close/func_string.php index 6c8c0c27..c84011af 100644 --- a/twe_close/func_string.php +++ b/twe_close/func_string.php @@ -301,4 +301,3 @@ class _String { } } -?> diff --git a/twe_close/install.php b/twe_close/install.php index 8deff41b..43790b5c 100644 --- a/twe_close/install.php +++ b/twe_close/install.php @@ -74,7 +74,7 @@ if(!$check) {
- +
diff --git a/twe_close/install2_ok.php b/twe_close/install2_ok.php index 9c83711c..1441a8a7 100644 --- a/twe_close/install2_ok.php +++ b/twe_close/install2_ok.php @@ -345,4 +345,3 @@ function insertCity($connect, $name, $level, $pop2, $agri2, $comm2, $secu2, $def ) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/twe_close/install3_ok.php b/twe_close/install3_ok.php index 3d4f74b0..5ff3b1d3 100644 --- a/twe_close/install3_ok.php +++ b/twe_close/install3_ok.php @@ -6,5 +6,5 @@ $connect=dbConn(); LogHistory($connect, 1); -echo ""; -?> +//echo ""; +echo 'index.php'; //TODO:replace diff --git a/twe_close/install_ok.php b/twe_close/install_ok.php index 3d0326c3..a4ae6fa8 100644 --- a/twe_close/install_ok.php +++ b/twe_close/install_ok.php @@ -5,6 +5,8 @@ include "func.php"; if(file_exists("d_setting/set.php")) error("이미 set.php가 생성되어 있습니다.

재설치하려면 해당 파일을 지우세요"); + + // 호스트네임, 아이디, DB네임, 비밀번호의 공백여부 검사 if(isBlank($hostname)) Error("HostName을 입력하세요",""); if(isBlank($user_id)) Error("User ID 를 입력하세요",""); @@ -83,7 +85,7 @@ if(!isTable($connect, "history",$dbname)) @MYDB_query($history_schema, $connect) // 파일로 DB 정보 저장 $file=@fopen("d_setting/set.php","w") or Error("set.php 파일 생성 실패

디렉토리의 퍼미션을 707로 주십시요",""); -@fwrite($file,"\n") or Error("set.php 파일 생성 실패

디렉토리의 퍼미션을 707로 주십시요",""); +@fwrite($file,"
디렉토리의 퍼미션을 707로 주십시요",""); @fclose($file); @mkdir("data",0707); @chmod("data",0707); @@ -94,4 +96,3 @@ $temp=MYDB_fetch_array(MYDB_query("select count(*) from general where level = '1 MYDB_close($connect); echo ""; -?> diff --git a/twe_close/join_post.php b/twe_close/join_post.php index 52384fb3..f6ab7941 100644 --- a/twe_close/join_post.php +++ b/twe_close/join_post.php @@ -272,4 +272,3 @@ if($id_num) { echo(""); } -?> diff --git a/twe_close/join_post.php.orig b/twe_close/join_post.php.orig index ed10c24b..c796b36b 100644 --- a/twe_close/join_post.php.orig +++ b/twe_close/join_post.php.orig @@ -272,4 +272,3 @@ if($id_num) { echo(""); } -?> diff --git a/twe_close/join_token.php b/twe_close/join_token.php index 87042ec3..dad9d390 100644 --- a/twe_close/join_token.php +++ b/twe_close/join_token.php @@ -55,4 +55,3 @@ $response['intel'] = $abil['intel']; usleep(100*1000); echo json_encode($response); -?> \ No newline at end of file diff --git a/twe_close/lib.php b/twe_close/lib.php index 75399e82..b0807cf0 100644 --- a/twe_close/lib.php +++ b/twe_close/lib.php @@ -7,7 +7,7 @@ // @header ("P3P : CP=\"ALL CURa ADMa DEVa TAIa OUR BUS IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC OTC\""); //디버그용 매크로 -define(__OLINE__,__LINE__); +define('__OLINE__',__LINE__); define(__LINE__,__FILE__." ".__FUNCTION__." ".__LINE__." : "); ini_set("session.cache_expire", 10080); // minutes ini_set("session.gc_maxlifetime", 604800); // seconds @@ -167,4 +167,3 @@ function PrintElapsedTime() { $_endTime = round(getMicroTime() - $_startTime, 3); echo "
경과시간 : {$_endTime}초
"; } -?> diff --git a/twe_close/license.txt b/twe_close/license.txt index ceed7e73..642b3e1a 100644 --- a/twe_close/license.txt +++ b/twe_close/license.txt @@ -1,36 +1 @@ -ZeroBoard에 대한 라이센스 명시입니다. - -아래 라이센스에 동의하시는 분만 제로보드를 사용할수 있습니다. - -프로그램명 : Zeroboard -배포버젼 : 4.1 pl 8 (2006. 3. 15) -개발자 : zero -Homepage : http://zeroboard.com - -1. 제로보드의 배포권은 ZEROBOARD.COM에서 허용한 곳에만 있습니다. - (허락 맡지 않은 재배포는 허용하지 않습니다.) - -2. 제로보드는 저작권을 아래 3번항목에 의해 표기하는 한도내에서 - 개인홈페이지 및 학교나 교회등의 비영리단체, 기업이나 기타 영리단체에서 사용할수 있습니다. - (반국가 단체나 불법 싸이트에서의 사용은 금지합니다) - -3. 제로보드 사용시 저작권 명시부분을 훼손하면 안됩니다. - 프로그램 소스, html소스상의 라이센스 및 웹상 출력물 하단에 있는 카피라이트와 링크를 수정하지 마십시요. - (저작권 표시는 게시판 배포시 작성된 형식만을 허용합니다. 임의 수정은 금지합니다) - -4. 단, 정식 등록버젼은 저작권 표시를 삭제할수 있습니다. - 정식 등록버젼에 대한 문의는 http://zeroboard.com 에서 문의 방법을 찾아주시기 바랍니다. - -5. 링크서비스등의 기본 용도에 맞지 않는 사용은 금지합니다. - -6. 제로보드의 사용으로 인한 데이타 손실 및 기타 손해등 어떠한 사고나 문제에 대해서 ZEROBOARD.COM은 절대 책임을 지지 않습니다. - -7. 제로보드에 대해 ZEROBOARD.COM은 유지/ 보수의 의무가 없습니다. - -8. 제로보드 소스는 개인적으로 사용시 수정하여 사용할수 있지만 수정된 프로그램의 재배포는 금지합니다. - (저작권 관련 부분은 수정금지입니다) - -9. 제로보드에 쓰인 스킨의 저작권은 스킨 제작자에게 있으며 제작자의 동의하에 수정배포가 가능합니다. - -10. 기타 의문사항은 http://zeroboard.com 을 이용해 주시기 바랍니다. - (질문등에 대한 내용은 메일로 받지 않습니다) +Ok Go! \ No newline at end of file diff --git a/twe_close/login_process.php b/twe_close/login_process.php index 1129f3c1..a3d56c76 100644 --- a/twe_close/login_process.php +++ b/twe_close/login_process.php @@ -78,4 +78,3 @@ function DeleteSession() { } MYDB_close($connect); -?> diff --git a/twe_close/logout_process.php b/twe_close/logout_process.php index 17b57479..d892aa75 100644 --- a/twe_close/logout_process.php +++ b/twe_close/logout_process.php @@ -16,10 +16,11 @@ $id = $me[user_id]; $pw = $me[password]; $conmsg = $me[conmsg]; -//Ǻ +//���Ǻ��� ���� session_destroy(); -echo ""; +//echo ""; +echo 'start.php';//TODO:replace /* @@ -33,4 +34,3 @@ a */ -?> diff --git a/twe_close/main.php b/twe_close/main.php index 352962ed..cf243bd1 100644 --- a/twe_close/main.php +++ b/twe_close/main.php @@ -334,5 +334,3 @@ banner(); if($con == 1) { MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^"); } if($me[newmsg] == 1) { MessageBox("개인 서신이 도착했습니다!"); } if($me[newvote] == 1) { $develcost = $admin[develcost]*5; MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)"); } -?> - diff --git a/twe_close/map.php b/twe_close/map.php index af42f272..8c33acb7 100644 --- a/twe_close/map.php +++ b/twe_close/map.php @@ -432,4 +432,3 @@ function getCityLevel($region, $level) { return $str; } -?> diff --git a/twe_close/map_history.php b/twe_close/map_history.php index 8f612467..8da98be7 100644 --- a/twe_close/map_history.php +++ b/twe_close/map_history.php @@ -31,4 +31,3 @@ $map = str_replace('<_quot_>', "'", $map); $map = str_replace('<_dquot_>', '"', $map); echo $map; -?> diff --git a/twe_close/npc_login_process.php b/twe_close/npc_login_process.php index 3dd7c0e5..969c95ae 100644 --- a/twe_close/npc_login_process.php +++ b/twe_close/npc_login_process.php @@ -73,4 +73,3 @@ function DeleteSession() { } MYDB_close($connect); -?> diff --git a/twe_close/phpinfo.php b/twe_close/phpinfo.php deleted file mode 100644 index cf608608..00000000 --- a/twe_close/phpinfo.php +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/twe_close/preprocessing.php b/twe_close/preprocessing.php index bcd7780b..b6e7ad95 100644 --- a/twe_close/preprocessing.php +++ b/twe_close/preprocessing.php @@ -120,5 +120,3 @@ switch($commandtype) { default: command_Other($connect, $turn, $commandtype); break; } -?> - diff --git a/twe_close/proc.php b/twe_close/proc.php index d1e4003d..7d9408b6 100644 --- a/twe_close/proc.php +++ b/twe_close/proc.php @@ -5,4 +5,3 @@ include "func.php"; $connect = dbConn(); increaseRefresh($connect, "자동", 2); checkTurn($connect); -?> diff --git a/twe_close/process_war.php b/twe_close/process_war.php index 6fba7ba9..f6825014 100644 --- a/twe_close/process_war.php +++ b/twe_close/process_war.php @@ -1845,4 +1845,3 @@ function ConquerCity($connect, $game, $general, $city, $nation, $destnation) { pushHistory($connect, $history); } -?> diff --git a/twe_close/processing.php b/twe_close/processing.php index e5949299..49788cdd 100644 --- a/twe_close/processing.php +++ b/twe_close/processing.php @@ -3125,5 +3125,3 @@ function command_81($connect, $turn, $command) { "; ender(1); } -?> - diff --git a/twe_close/queue.php b/twe_close/queue.php index 05800144..7fa94915 100644 --- a/twe_close/queue.php +++ b/twe_close/queue.php @@ -38,4 +38,3 @@ class Queue { return $value; } } -?> diff --git a/twe_close/reset.php b/twe_close/reset.php index 07c170b3..98d01c04 100644 --- a/twe_close/reset.php +++ b/twe_close/reset.php @@ -67,7 +67,7 @@ if(!isTable($connect, "history",$dbname)) @MYDB_query($history_schema, $connect) // 파일로 DB 정보 저장 $file=@fopen("d_setting/set.php","w") or Error("set.php 파일 생성 실패

디렉토리의 퍼미션을 707로 주십시요",""); -@fwrite($file,"\n") or Error("set.php 파일 생성 실패

디렉토리의 퍼미션을 707로 주십시요",""); +@fwrite($file,"
디렉토리의 퍼미션을 707로 주십시요",""); @fclose($file); @mkdir("data",0707); @chmod("data",0707); @@ -78,4 +78,3 @@ $temp=MYDB_fetch_array(MYDB_query("select count(*) from general where level = '1 MYDB_close($connect); echo ""; -?> diff --git a/twe_close/scenario_1.php b/twe_close/scenario_1.php index d62efaf9..e39633f0 100644 --- a/twe_close/scenario_1.php +++ b/twe_close/scenario_1.php @@ -792,4 +792,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_10.php b/twe_close/scenario_10.php index b6ba094e..47588492 100644 --- a/twe_close/scenario_10.php +++ b/twe_close/scenario_10.php @@ -898,4 +898,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_11.php b/twe_close/scenario_11.php index 47ef5b88..e064095a 100644 --- a/twe_close/scenario_11.php +++ b/twe_close/scenario_11.php @@ -897,4 +897,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_12.php b/twe_close/scenario_12.php index 89d6ff15..73d612cc 100644 --- a/twe_close/scenario_12.php +++ b/twe_close/scenario_12.php @@ -1181,4 +1181,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_2.php b/twe_close/scenario_2.php index 32fc1329..8340b15b 100644 --- a/twe_close/scenario_2.php +++ b/twe_close/scenario_2.php @@ -1711,4 +1711,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_20.php b/twe_close/scenario_20.php index d23ac02d..a4ae577f 100644 --- a/twe_close/scenario_20.php +++ b/twe_close/scenario_20.php @@ -746,4 +746,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_21.php b/twe_close/scenario_21.php index 117867cb..6dd317b0 100644 --- a/twe_close/scenario_21.php +++ b/twe_close/scenario_21.php @@ -774,4 +774,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_22.php b/twe_close/scenario_22.php index 0243103b..5176501c 100644 --- a/twe_close/scenario_22.php +++ b/twe_close/scenario_22.php @@ -194,4 +194,3 @@ function RegGeneral2($connect,$turnterm,$gencount,$name,$leader,$power,$intel,$p } } -?> diff --git a/twe_close/scenario_23.php b/twe_close/scenario_23.php index b4804c15..dee04c1c 100644 --- a/twe_close/scenario_23.php +++ b/twe_close/scenario_23.php @@ -750,4 +750,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_24.php b/twe_close/scenario_24.php index 5053015c..8fb46725 100644 --- a/twe_close/scenario_24.php +++ b/twe_close/scenario_24.php @@ -325,4 +325,3 @@ function RegGeneral3($connect,$turnterm,$gencount,$nation,$level,$name,$leader,$ ) or Error(__LINE__.MYDB_error($connect),""); } -?> diff --git a/twe_close/scenario_25.php b/twe_close/scenario_25.php index 88ac73e7..906f1525 100644 --- a/twe_close/scenario_25.php +++ b/twe_close/scenario_25.php @@ -316,4 +316,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_26.php b/twe_close/scenario_26.php index 271f7876..4f32a294 100644 --- a/twe_close/scenario_26.php +++ b/twe_close/scenario_26.php @@ -313,4 +313,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_27.php b/twe_close/scenario_27.php index 4e66d967..46082d2b 100644 --- a/twe_close/scenario_27.php +++ b/twe_close/scenario_27.php @@ -591,4 +591,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_28.php b/twe_close/scenario_28.php index 9ceca2d3..f233c2bd 100644 --- a/twe_close/scenario_28.php +++ b/twe_close/scenario_28.php @@ -420,4 +420,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_3.php b/twe_close/scenario_3.php index a8c77239..34380b1f 100644 --- a/twe_close/scenario_3.php +++ b/twe_close/scenario_3.php @@ -1752,4 +1752,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_4.php b/twe_close/scenario_4.php index 8658a05c..ffc45ada 100644 --- a/twe_close/scenario_4.php +++ b/twe_close/scenario_4.php @@ -1289,4 +1289,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_5.php b/twe_close/scenario_5.php index 450bfc4c..c621480b 100644 --- a/twe_close/scenario_5.php +++ b/twe_close/scenario_5.php @@ -995,4 +995,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_6.php b/twe_close/scenario_6.php index a4d83d3f..f697a60f 100644 --- a/twe_close/scenario_6.php +++ b/twe_close/scenario_6.php @@ -1041,4 +1041,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_7.php b/twe_close/scenario_7.php index c56de9aa..8cc61f2d 100644 --- a/twe_close/scenario_7.php +++ b/twe_close/scenario_7.php @@ -1093,4 +1093,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_8.php b/twe_close/scenario_8.php index b02d6e0d..6529ca47 100644 --- a/twe_close/scenario_8.php +++ b/twe_close/scenario_8.php @@ -945,4 +945,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/scenario_9.php b/twe_close/scenario_9.php index 5e49bddc..ba703829 100644 --- a/twe_close/scenario_9.php +++ b/twe_close/scenario_9.php @@ -869,4 +869,3 @@ pushHistory($connect, $history); echo ""; -?> diff --git a/twe_close/schema.php b/twe_close/schema.php index 9479dc2a..ceb9050d 100644 --- a/twe_close/schema.php +++ b/twe_close/schema.php @@ -617,5 +617,3 @@ $history_schema = " "; -?> - diff --git a/twe_close/schema.sql.orig b/twe_close/schema.sql.orig index 1654fc77..fa3318af 100644 --- a/twe_close/schema.sql.orig +++ b/twe_close/schema.sql.orig @@ -617,5 +617,3 @@ $history_schema = " "; -?> - diff --git a/twe_close/select_npc_post.php b/twe_close/select_npc_post.php index 9de8fccc..ebe9997c 100644 --- a/twe_close/select_npc_post.php +++ b/twe_close/select_npc_post.php @@ -124,4 +124,3 @@ if($admin[npcmode] != 1) { echo(""); } -?> diff --git a/twe_close/turn.php b/twe_close/turn.php index 8b475519..f7373898 100644 --- a/twe_close/turn.php +++ b/twe_close/turn.php @@ -85,6 +85,3 @@ case 2: } echo ""; - -?> - diff --git a/twe_close/turn_pop_core.php b/twe_close/turn_pop_core.php index d40de774..4198b506 100644 --- a/twe_close/turn_pop_core.php +++ b/twe_close/turn_pop_core.php @@ -12,6 +12,3 @@ $me = MYDB_fetch_array($result); updateCommand($connect, $me[no], 2); echo ""; - -?> - diff --git a/twe_close/turn_push_core.php b/twe_close/turn_push_core.php index b680cd17..740ae1a7 100644 --- a/twe_close/turn_push_core.php +++ b/twe_close/turn_push_core.php @@ -13,5 +13,3 @@ backupdateCommand($connect, $me[no], 2); echo ""; -?> -