19 Commits
7.0.1 ... 8.0.0

Author SHA1 Message Date
Leo Khoa
ea6254fc80 Laragon 8.0.0 2025-03-13 21:25:13 +01:00
Leo Khoa
566be5ce9f Update sites.conf 2025-03-13 21:24:27 +01:00
Leo Khoa
959aab1bc7 Merge pull request #1057 from leokhoa/leokhoa-patch-3
Update packages.conf
2025-03-13 21:22:50 +01:00
Leo Khoa
3f0534e0e1 Update packages.conf 2025-03-13 21:22:11 +01:00
Leo Khoa
6d0ca768f9 Update packages.conf
Fix broken PHP links
2025-02-27 08:18:10 +01:00
Leo Khoa
1bf6169ffc Track changes from version 7.0.0 2025-02-06 11:04:39 +01:00
Leo Khoa
6959b13189 Fix css issue
https://github.com/leokhoa/laragon/issues/339
2025-02-03 22:33:56 +01:00
Leo Khoa
2631fda37b Fix bug #689
https://github.com/leokhoa/laragon/issues/689
2025-02-03 22:32:38 +01:00
Leo Khoa
3fcd32d767 Merge pull request #1007 from leokhoa/leokhoa-patch-2
Update SECURITY.md
2025-02-02 13:01:08 +01:00
Leo Khoa
b371252f27 Update SECURITY.md 2025-02-02 13:00:25 +01:00
Leo Khoa
18992b2d5c Improve Laragon to work with virtual machine 2025-01-28 20:09:08 +01:00
Leo Khoa
5cf5f6b2ae Add more logs 2025-01-28 18:38:13 +01:00
Leo Khoa
45d2c3f117 Delete etc/apps directory as it is obsolete 2025-01-27 19:57:51 +01:00
Leo Khoa
f58e47d630 Merge pull request #988 from leokhoa/security_md
Create SECURITY.md
2025-01-26 22:22:57 +01:00
Alexander Walther
b23f970bea Create SECURITY.md 2025-01-26 22:10:16 +01:00
Leo Khoa
f9f71aa06b 7.0.2 -> Rollback pretty url to .test 2025-01-25 22:00:23 +01:00
Leo Khoa
93a49297b6 Rolllback to use .test for pretty url
Laragon 7.0.2
2025-01-25 21:56:37 +01:00
Leo Khoa
97b9cff42a Update PHP links 2025-01-25 00:29:40 +01:00
Leo Khoa
d62e7dd284 Update pretty url ---> https://app.localhost 2025-01-25 00:26:01 +01:00
52 changed files with 339 additions and 7075 deletions

1
CHANGELOG.md Normal file
View File

@@ -0,0 +1 @@

13
SECURITY.md Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
| Version | Supported |Reason |
| ------- | ------------------ | ---------- |
| >=7.0 | :white_check_mark: | |
| <=6.0 | :x: | EOL |
## Reporting a Vulnerability
If you find a security vulnerability in Laragon, please report it via email to Leo Khoa at leo@laragon.org
We take security seriously, and all reports will be promptly addressed.

View File

@@ -250,14 +250,14 @@ date: 20181016
# Setup # Setup
900 = يعمل لاراقون بشكل سريع جداً ولديه مساحة ذاكرة منخفضة جداً ( <4 ميجابايت) 900 = يعمل لاراقون بشكل سريع جداً ولديه مساحة ذاكرة منخفضة جداً ( <4 ميجابايت)
901 = سيحصل تطبيقك على رابط لطيف ---> http://app.test 901 = سيحصل تطبيقك على رابط لطيف ---> https://app.test
902 = أضف محرر النص و موجه الأوامر إلى قائمة النقر بزر الفأرة الأيمن 902 = أضف محرر النص و موجه الأوامر إلى قائمة النقر بزر الفأرة الأيمن
903 = طرق سريعة لفتح محرر النصوص وموجه الاوامر 903 = طرق سريعة لفتح محرر النصوص وموجه الاوامر
904 = عرض ملف اقرئني 904 = عرض ملف اقرئني
905 = تشغيل لاراقون 905 = تشغيل لاراقون
# SSL # SSL
906 = إنشاء تلقائي لشهادات SSL 906 = Auto-generated SSL Certificates
# Version 3 # Version 3
140 = تجهيز البيانات... 140 = تجهيز البيانات...
@@ -289,4 +289,4 @@ date: 20181016
# Version 3.5 # Version 3.5
920 = استنساخ 920 = استنساخ
921 = اختر مشروعًا لإستنساخه 921 = اختر مشروعًا لإستنساخه
922 = قاعدة البيانات المستنسخة! 922 = قاعدة البيانات المستنسخة!

View File

@@ -250,7 +250,7 @@ date: 20192108
# Setup # Setup
900 = Laragon runs extremely fast and has very low memory footprint (< 4 MB) 900 = Laragon runs extremely fast and has very low memory footprint (< 4 MB)
901 = Sizin tətbiqiniz qısa yol əldə edəcək ---> http://app.test 901 = Sizin tətbiqiniz qısa yol əldə edəcək ---> https://app.test
902 = Sublime Text əlavə et && Terminal to the Right-Click Menu 902 = Sublime Text əlavə et && Terminal to the Right-Click Menu
903 = Text editləyicini açmaq üçün sürətli yollar & Əmr lövhəsi 903 = Text editləyicini açmaq üçün sürətli yollar & Əmr lövhəsi
904 = README faylına bax 904 = README faylına bax

View File

@@ -252,7 +252,7 @@ date: 20161113
# Setup # Setup
900 = Laragon работи изключително бързо и използв много малко от РАМ (< 4 MB) 900 = Laragon работи изключително бързо и използв много малко от РАМ (< 4 MB)
901 = Твоето приложение ще изполва "красиви" линкове ---> http://app.test 901 = Твоето приложение ще изполва "красиви" линкове ---> https://app.test
902 = Добави Sublime Text && Terminal в меню от десен клик 902 = Добави Sublime Text && Terminal в меню от десен клик
903 = Лесен начин да стартиране Текстов редактор & Команден прозорец 903 = Лесен начин да стартиране Текстов редактор & Команден прозорец
904 = Покажи README файла 904 = Покажи README файла

View File

@@ -253,7 +253,7 @@ date: 20190827
# Setup # Setup
900=Laragon运行得非常快具有非常低的内存占用小于4 MB 900=Laragon运行得非常快具有非常低的内存占用小于4 MB
901=你的“项目”将得到优雅链接 ---> http://项目.test 901=你的“项目”将得到优雅链接 ---> https://项目.test
902=添加 Sublime Text 和 Terminal 到右击菜单 902=添加 Sublime Text 和 Terminal 到右击菜单
903=快速打开 文本编辑器 和 命令行 903=快速打开 文本编辑器 和 命令行
904=查看README文件 904=查看README文件

View File

@@ -1,292 +1,257 @@
-------------------------------------------------------- --------------------------------------------------------
author: SiderealArt - admin at siderealart.me - https://siderealart.me/ author: Kyomini - Kyomini@qq.com - https://laragon.com.cn
date: 20220125 date: 20160802
Language Traditional Chinese Language Traditional Chinese
-------------------------------------------------------- --------------------------------------------------------
#主界面 #主界面
100=全部啟動 100=啟動所有
101=網站 101=網站
102=資料 102=數據
103=終端 103=終端
104=根目錄 104=根目錄
105=停止 105=停止
106=正在停止... 106=停止...
107=重新載 107=重新
108=啟動 108=啟動
109=版本 109=版本
110=已啟用 110=已啟用
111=全部停止 111=停止所有
112=關閉 112=關閉
113=最小化 113=最小化
114=最大化 114=最大化
115=是 115=是
116=否 116=否
117=取消 117=取消
118=OK 118=好的
119=開 119=開
120=關 120=關
121= 121=
122=如有任何問題,歡迎聯絡我們 122=如有任何問題,請隨時聯系!
# Menu # Menu
199=www 199=www
200=工具 200=工具
201=PATH 環境變 201=PATH 環境變
202=傳輸檔案 202=傳輸文件
203=建立專案 203=創建項目
204=切換專案 204=切換項目
205=建立資料 205=創建數據
206=更換 root 密碼 206=更換root密碼
207=郵件接收 207=郵件接收
208=查看最新郵件 208=查看最新郵件
209=打開郵路徑 209=打開郵路徑
210=取 sendmail_path 210=取 sendmail_path
211=設定 211=配置
212=郵件 212=郵件
213=擴充功能 213=擴
214=網站後臺 214=網站後臺
215=登 215=登
216=設定 216=參數
217=退出 217=退出
218=專案名稱 218=項目名稱
# 首選項 # 首選項
300=一般 300=常規
301=服務 && 連接埠 301=服務 && 端口
310=讓 Laragon 隨 Windows 啟動 310=Windows系統啟動時運行Laragon
311=讓 Laragon 隨 Windows 自動啟動 311=Windows系統啟動時自動運行Laragon
312=啟動後最小化 312=最小化運行
# \n for a new line # \n for a new line
313=Laragon 最小化到系統匣。\n左鍵點擊系統匣的 Laragon 圖示來開啟 Laragon 313=Laragon最小化到系統托盤\n左擊系統托盤Laragon圖標顯示Laragon
314=自動啟動所有服務 314=自動啟動所有服務
315=當 Laragon 運行時自動啟動所有選擇的服務 315=當Laragon運行時自動啟動所有選擇的服務
316=語言 316=語言
317=檔案根目錄 317=文件根目錄
318=點擊更換檔案根目錄 318=點擊更換文件根目錄
319=資料路徑 319=數據路徑
320=點擊更換 MySQL 資料路徑 320=點擊更換MySQL數據路徑
322=自動建虛擬主機 322=自動建虛擬主機
323=只需放置資料夾到檔案根目錄 & 重新載入 ApacheLaragon 將自動建對應的主機名稱到 hosts 檔案和Apache虛擬主機 323=只需放置文件夾到文件根目錄 &重載ApacheLaragon將自動建對應的主機名hosts文件和Apache虛擬主機
# %s for a string placeholder # %s for a string placeholder
324=主機名稱格式 324=主機名
325=主機名格式.\n例如: 如果您的專案名是 %s 325=主機名格式.\n例如: 如果妳的項目名是 %s
328=進階 328=高級項
329=當呼叫 mail() 函數Laragon 將在畫面右下角\n顯示郵件資訊。 329=當調用 mail() 函數Laragon將顯示生成的郵件信息\n在妳屏幕右下角的小窗口裏
330=窗將顯示 330=窗將顯示
331=此功能將幫助快速瀏覽郵件內容\n也可以透過:\n單 > PHP > MailCatcher 來檢視最新郵件的內容 331=此特性將幫助快速瀏覽郵件內容.\n也可以任何時候瀏覽最新郵件:\n單 > PHP > 郵件接收
340=Gmail 帳號 340=Gmail 地址
341=Gmail 密碼 341=Gmail 密碼
342=測試送郵件 342=測試送郵件
343=您可能需要在您的 Google 帳號中允許 「低安全性應用程式存取」。\n您的 Gmail 密碼將被加密\n啟用後可以輸入此行指令來輕鬆的傳送電子郵件: 343=妳看到的Gmail密碼將被加密\n啟用後,可以通過互聯網輕松發送郵件,只需壹行:
# 郵件分析儀 # 郵件分析儀
350=郵件分析 350=郵件分析
351=送測試郵件到 351=送測試郵件到
352=重新測試 352=重新測試
353=重新測試發送郵件,可以輸入其他電子郵件地址來測試。 353=重新測試發送郵件,可以輸入另外的郵箱地址來測試。
354=關閉 354=關閉
# 系統托盤 # 系統托盤
400=Laragon 已最小化 400=Laragon已最小化
401=切換至專案: 401=切換項目:
402=已建立資料庫! 402=已創建數據庫!
403=更改 MySQL 資料庫 root 密碼成功! 403=更改MySQL數據庫root密碼成功
404=Apache 已重新載 404=Apache 已重新載!
405=路徑錯誤! 405=錯誤路徑
406=偵測到新專案\nLaragon 將呼叫 Node.js 來幫您建立虛擬主機! 406=偵測到新項目\nLaragon 將調用NodeJs來為妳創建虛擬主機!
# 提示 # 提示
500=線幫助 500=線幫助
501=左鍵點擊:Laragon - 右鍵點擊:選 501=左鍵單擊: Laragon - 右鍵單擊: 菜
502=開始頁面 502=開始頁面
503=資料庫管理 503=數據庫管理
504=打開命令提示字元 (快捷鍵: CTRL+ALT+T) 504=打開命令提示 (快捷鍵: CTRL+ALT+T)
505=Laragon 將會呼叫 Node.js 來建立虛擬主機\n若您不想要使用 Node.js\n請以管理員身分執行 Laragon 505=Laragon將會調用Nodejs來創建虛擬主機 \n如果妳想要這個功能無需調用Nodejs \n作為Administrator運行Laragon
506=檔根目錄 506=檔根目錄
# Quick create website/project # Quick create website/project
600=正在建立 600=創建中
601=已建 601=已
602=正在下載 602=下載
603=已完成下載 603=已下載
604=正在解壓縮 604=提取中
605=已完成解壓縮 605=已提取
606=產生美化連結 606=生成優雅鏈接
607=快速建 607=快速
608=網站名稱 608=網站名稱
609=請指定專案名稱 609=請指定項目名
610=已建立 %s 610=%s 已創建
611=無法建 %s原因%s 611=無法建 %s ,原因如下: %s
612=瀏覽 612=瀏覽
613=點擊前往專案資料 613=點擊前往項目文件
614=點擊瀏覽網站 614=點擊瀏覽網站
# Messages # Messages
700=已複製 sendmail_path 到剪貼簿 700=sendmail_path已復制到粘貼板
701=此功能無法在您電腦上使用! 701=此特性無法在您電腦上使用!
702=請先啟動 %s 702=請先啟動 %s
703=名稱無效! 703=名稱無效!
704=此目錄未包含有效的 Laravel 專案 704=此目錄未包含壹個有效的Laravel項目
705=請啟動 PHP 服務! 705=請打開PHP服務
706=前往單 > 設定 > 服務 & 連接埠,並啟PHP 服務 706=前往單 > 參數 > 服務 & 端口,並啟PHP服務
707=專案已存在! 707=項目已存在!
708=如果真的想要建立此專案,請先刪除專案資料夾並重試 708=如果真的希望創建這個項目,嘗試刪除此項目文件夾
709=無資料夾! 709=無文件夾
710=無檔案! 710=無文件
711=%s 未行,請先啟動 Redis 伺服器 711=%s 未請先啟動Redis服務
712=請不要在 Laragon 安裝路徑中使用空格 (為避免以後的麻煩) 712=請不要在Laragon安裝路徑中使用空格(為避免以後的麻煩)
713=%s 服務正在行,但在其他處理程序下。 713=%s 服務正在行,但在其他進程
714=請停止您目前的 WAMP 堆疊,否則 Laragon 將會出現未知錯誤 714=請停止妳當前的WAMP堆棧否則Laragon將會出現未知錯誤
715=處理程序路徑 715=進程路徑:
# Hope you never see this :) # Hope you never see this :)
716=哦Laragon 偵測到例外狀況 716=哦NoLaragon檢測到異常
717=無法建立資料庫 %s原因%s 717=無法創建數據庫 %s ,原因是: %s
718=無法更改 MySQL root 密碼,原因%s 718=無法更改MySQL root密碼原因是: %s
719=必須提供有效的 Gmail 帳號! 719=必須指定壹個有效的Gmail地址
720=無法在啟動資料夾中建立捷徑 720=無法在啟動目錄創建快捷方式
721=無法啟動資料夾刪除捷徑 721=無法啟動目錄中刪除快捷方式
722=格式錯誤!必須含有專案名稱格式 {name}.xxx 722=錯誤的格式!必須要有壹個項目名稱模式在{name}.xxx!
723=格式錯誤!主機名稱無效 723=錯誤的格式!不是壹個有效的主機名
724=MySQL 資料路徑無效! 724=不是有效的MySQL數據路徑!
725=必須在選單 > 設定 > 服務 & 連接埠中啟用 Apache MySQL 服務! 725=必須啟用Apache MySQL服務在 services in 菜單 > 參數 > 服務 & 端口
# When Laragon can not modify hosts file # When Laragon can not modify hosts file
726=哎呀!您的系統阻止更改 hosts 檔案。\n請檢查您的防毒軟體和安全性分頁中的權限,查看檔案是否為唯讀\ nLaragon 將暫時停用 「自動建立虛擬主機功能! 726=哎呀!妳的系統阻止更改hosts文件\n請檢查妳的殺毒軟件或權限的安全選項卡或檢查的文件是否是只讀文件\ nLaragon將暫時停用“自動創建虛擬主機功能!
727=為了使此功能生效,可以試試:\n1 前往:%s\drivers\etc\n2右鍵點擊 hosts 檔案並取消勾選唯讀核取方塊。 727=為了使這壹特征生效,可以試試:\n1 轉到: %s\drivers\etc\n2 右鍵單擊hosts文件並取消只讀復選框
728=提醒hosts 檔案目前權限 728=註意:當前hosts文件權限:
# hosts file is Read-only # hosts file is Read-only
729= 729=
# Write permission in Security tab # Write permission in Security tab
730=安全 > 寫入 730=安全 > 寫入
# MySQL
800=資料庫名稱 800=數據庫名稱
801=新密碼 801=新密碼
802=密碼 802=當前密碼
# Version 2 # Version 2
219=Ngrok 219=Ngrok
220=分享 220=分享
221=Ngrok 連結已複製到剪貼簿 221=Ngrok鏈接已復制到粘貼板
222=Ngrok 通道已就緒 222=Ngrok 通道已經準備好
223=點擊以手動以管理員身分編輯 host 檔案 223=作為管理員手動編輯hosts文件
224=已開始 224=已開始
226=解壓縮 226=解
227=已解壓縮 227=已解
228=不支援此格式 228=不是支持的格式
229=請耐心等待直到解壓縮完成 229=請耐心等待直到接收完成
230=連結錯誤 230=錯誤鏈接
231=下載時發生錯誤,請試! 231=當您下載時發生錯誤,請再嘗試!
232=發生錯誤!也許的下載連結錯誤。 232=發生錯誤!也許的下載鏈接是錯誤
233=請檢查連結並重 233=請檢查鏈接並嘗
234=瀏覽網站 234=瀏覽網站
235=關閉並瀏覽網站 235=關閉並瀏覽網站
236=編輯 236=編輯
237=切換檔案目錄 237=切換文檔根目錄
238=選取其他 238=選擇另外壹個
239=資料庫已存在! 239=數據庫已存在!
240=如果未知請留空 240=如果不知道請留空
241=Apache的 SSL 連接埠預設為停用,勾選以啟用 241=Apache的 SSL 端口默認是關閉的,檢查後啟用
242=已產生 SSL 證! 242=生 SSL 證
243=必須先點擊 [%s] 243=必須先點擊 [%s]
244=自動建立資料 244=自動創建數據
245=如何強制 Wordpress 使用相對路徑 245=如何強制Wordpress使用相對路徑
246=左 246=左
247=右 247=右
248=Laragon 安裝根目錄 248=Laragon 安裝根目錄
249=全部刪除 [自動] 249=刪除所有 [自動]
250=設定檔 250=設置文件
251=啟動 251=啟動文件
252=如何新增其他 %s 版本 252=如何添加另外壹個 %s 版本
253=Laragon 已在執行! 253=Laragon正在運行!
# Reset & generate a random password for root # Reset & generate a random password for root
803=重置並產生一個隨機的 root 密碼 803=重置並生產壹個隨機的root密碼
804=解決方案:重置 MySQL root 密碼 804=妳可以梳理問題,重置MySQL root密碼
805=偵測 MySQL 是否正在 805=檢測如果MySQL正在
806=%s 正在執行,PID %d 806=%s 正在運行 PID %d
807=找到一個處理程序 807=發現壹個進程
808=必須先停止 MySQL 伺服器 808=必須先停止正在運行的MySQL
810=%s 選項啟動 MySQL 服務 810=%s 選項啟動MySQL服務
811=重置 root 密碼 & 產生一個隨機密碼 811=重置root密碼 & 生成壹個隨機密碼
812=已成功重置和產生 MySQL root 密碼! 812=重置&生成MySQL root密碼
813=已複製到剪貼簿:%s 813=已復制到粘貼板: %s
814=發生錯誤!%s 814=發生錯誤! %s
815=正在停止 MySQL - PID %d 815=停止 MySQL - PID %d
816=無法停止正在執行的 MySQL - PID %d 816=無法停止當前運行的 MySQL - PID %d
817=您可以試試手動重置%s 817=妳需要手動重置: %s
818=完成 818=完成
# Windows Explorer's Context Menu - && is not typo # Windows Explorer's Context Menu - && is not typo
830=右鍵選 830=右擊 菜
831=加入 Sublime Text && 終端機 831=添加/更新 Sublime Text && Terminal
832=移除 Sublime Text && 終端機 832=移除 Sublime Text && Terminal
833=使用 Sublime Text 編輯 833=使用Sublime Text編輯
834=使用 Sublime Text 打開資料 834=使用Sublime Text打開文件
836=請管理員身分開啟 Laragon 並重試 836=請嘗試管理員身份運行Laragon
# Setup # Setup
900=Laragon 的執行速度飛快,且記憶體占用率極低(小於 4 MB 900=Laragon運行得非常快,具有非常低的內存占用小於4 MB
901=美化您的應用程式的網址 ---> http://app.test 901=妳的“項目”將得到優雅鏈接 ---> https://項目.test
902= Sublime Text 和 終端機加入右鍵選 902=添加 Sublime Text 和 Terminal 到右擊菜
903=快速打開文字編輯器及終端機 903=快速打開 文本編輯器 和 命令行
904=查看 README 文件 904=查看README文件
905=開啟 Laragon 905=運行Laragon
# SSL
906 = 自動產生 SSL 憑證
# Version 3
140 = 正在初始化資料...
141 = 無法初始化資料,請重試!
142 = Region
150 = 將 Laragon 加入 Path 環境變數
151 = 將 Laragon 從 Path 環境變數中移除
152 = 管理 Path 環境變數
153 = 已將 Laragon 加入 Path您可能需要重新登入以套用變更。
154 = 已將 Laragon 從 Path 中移除!
155 = 全部關閉
156 = 自動執行
157 = 正在停止執行中的服務...
158 = 幫助
# Version 3.1.3
159 = 自動產生 QR Code
# Version 3.3.1
160 = SSL 已啟用。點擊此處以停用
161 = 將 laragon.crt 加入至 Trust Store
162 = 憑證管理員
163 = 快捷設定
164 = 如何管理 "%s"
165 = 如何將 Xdebug 加入 Laragon
166 = WildcardDNS
167 = 這是什麼?
# Version 3.5
920 = 複製
921 = 選擇要複製的專案
922 = 已複製資料庫!

View File

@@ -1,6 +1,6 @@
-------------------------------------------------------- --------------------------------------------------------
version: 1.0 version: 1.0
author: Claus Munch - claus@codepoint.dk - http://codepoint.dk author: Claus Munch - claus@codepoint.dk - https://codepoint.dk
date: 20160511 date: 20160511
-------------------------------------------------------- --------------------------------------------------------
# Main Interface # Main Interface

View File

@@ -250,7 +250,7 @@ date: 20201115
# Setup # Setup
900 = Laragon functioneert extreem snel en heeft een zeer laag geheugen verbruik (< 4 MB) 900 = Laragon functioneert extreem snel en heeft een zeer laag geheugen verbruik (< 4 MB)
901 = Je app zal een mooie url krijgen ---> http://app.test 901 = Je app zal een mooie url krijgen ---> https://app.test
902 = Toevoegen Sublime Text && Terminal aan het Rechtermuisklik Menu 902 = Toevoegen Sublime Text && Terminal aan het Rechtermuisklik Menu
903 = Snelle manieren om Tekstverwerker en Opdrachtprompt te openen 903 = Snelle manieren om Tekstverwerker en Opdrachtprompt te openen
904 = Bekijken het README bestand 904 = Bekijken het README bestand

View File

@@ -1,7 +1,7 @@
-------------------------------------------------------- --------------------------------------------------------
version: 3.5 version: 7.0.1
author: leokhoa - leokhoa at gmail.com - https://laragon.org author: leokhoa - leokhoa at gmail.com - https://laragon.org
date: 20181016 date: 20250124
-------------------------------------------------------- --------------------------------------------------------
# Main Interface # Main Interface
100 = Start All 100 = Start All
@@ -111,7 +111,7 @@ date: 20181016
501 = Left click: Open Laragon - Right click: Menu 501 = Left click: Open Laragon - Right click: Menu
502 = Start page 502 = Start page
503 = Database Management 503 = Database Management
504 = Open Command Prompt (Hotkey: CTRL+ALT+T) 504 = Open Terminal (Cmder)
505 = Laragon will call nodejs to create virtual hosts for you\nIf you want this feature without calling nodejs:\nRun Laragon as Administrator 505 = Laragon will call nodejs to create virtual hosts for you\nIf you want this feature without calling nodejs:\nRun Laragon as Administrator
506 = Document Root 506 = Document Root
@@ -250,7 +250,7 @@ date: 20181016
# Setup # Setup
900 = Laragon runs extremely fast and has a very low memory footprint (< 4 MB) 900 = Laragon runs extremely fast and has a very low memory footprint (< 4 MB)
901 = Your app will get a pretty url ---> http://app.test 901 = Your app will get a pretty url ---> https://app.test
902 = Add Sublime Text && Terminal to the Right-Click Menu 902 = Add Sublime Text && Terminal to the Right-Click Menu
903 = Quick ways to open Text Editor & Command Prompt 903 = Quick ways to open Text Editor & Command Prompt
904 = View the README file 904 = View the README file
@@ -290,3 +290,10 @@ date: 20181016
920 = Clone 920 = Clone
921 = Select a project to clone 921 = Select a project to clone
922 = Cloned database! 922 = Cloned database!
# version 7.0 Laragon 2025
929 = Current profile
930 = New profile
931 = Profile Name
932 = Action

View File

@@ -248,7 +248,7 @@ date: 20181219
# Setup # Setup
900=Laragon se lance extrêmement rapidement et a une empreinte mémoire très basse (< 4 MB) 900=Laragon se lance extrêmement rapidement et a une empreinte mémoire très basse (< 4 MB)
901=Votre application aura une jolie URL ---> http://app.test 901=Votre application aura une jolie URL ---> https://app.test
902=Ajouter Sublime Text et le terminal au menu contextuel 902=Ajouter Sublime Text et le terminal au menu contextuel
903=Façon rapide d'ouvrir l'éditeur de texte et le terminal 903=Façon rapide d'ouvrir l'éditeur de texte et le terminal
904=Voir le fichier README 904=Voir le fichier README

View File

@@ -250,7 +250,7 @@ date: 20160715
# Setup # Setup
900=Laragon läuft extrem performant und hat einen sehr geringen Speicherverbrauch (< 4 MB) 900=Laragon läuft extrem performant und hat einen sehr geringen Speicherverbrauch (< 4 MB)
901=Ihre Anwendung bekommt diese URL ---> http://app.test 901=Ihre Anwendung bekommt diese URL ---> https://app.test
902=Sublime Text && Terminal zum Kontextmenü hinzufügen 902=Sublime Text && Terminal zum Kontextmenü hinzufügen
903=Schnelles öffnen des Text-Editors und der Konsole 903=Schnelles öffnen des Text-Editors und der Konsole
904=README-Datei öffnen 904=README-Datei öffnen

View File

@@ -247,7 +247,7 @@ date: 20161025
# Setup # Setup
900=Το Laragon είναι ταχύτατο και καταναλώνει ελάχιστη μνήμη (< 4 MB) 900=Το Laragon είναι ταχύτατο και καταναλώνει ελάχιστη μνήμη (< 4 MB)
901=Η εφαρμογή σου θα αποκτήσει pretty url ---> http://app.test 901=Η εφαρμογή σου θα αποκτήσει pretty url ---> https://app.test
902=Προσθήκη του Sublime Text && Τερματικό στο μενού του δεξιού κλικ 902=Προσθήκη του Sublime Text && Τερματικό στο μενού του δεξιού κλικ
903=Φρήγοροι τρόποι να ανοίξεις τον επεξεργαστή κειμένου και το τερματικό 903=Φρήγοροι τρόποι να ανοίξεις τον επεξεργαστή κειμένου και το τερματικό
904=Δες το αρχείο README 904=Δες το αρχείο README

View File

@@ -250,7 +250,7 @@ date: 20191016
# Setup # Setup
900 = A Laragon rendkívül gyors és alacsony memóriaigényű alkalmazás (< 4 MB) 900 = A Laragon rendkívül gyors és alacsony memóriaigényű alkalmazás (< 4 MB)
901 = Alkalmazása szép url-t kap ---> http://app.test a http://localhost/app helyett 901 = Alkalmazása szép url-t kap ---> https://app.test a https://localhost/app helyett
902 = Sublime Text és Terminál hozzáadása az intéző helyi menüjéhez 902 = Sublime Text és Terminál hozzáadása az intéző helyi menüjéhez
903 = Így a szövegszerkesztő és a parancssoros terminál gyors megnyitható 903 = Így a szövegszerkesztő és a parancssoros terminál gyors megnyitható
904 = README (olvass el) fájl megnyitása 904 = README (olvass el) fájl megnyitása

View File

@@ -250,7 +250,7 @@ date: 20181016
# Setup # Setup
900 = Laragon berjalan sangat cepat dan memiliki jejak memori yang sangat rendah (< 4 MB) 900 = Laragon berjalan sangat cepat dan memiliki jejak memori yang sangat rendah (< 4 MB)
901 = Aplikasi Anda akan mendapatkan url yang cantik ---> http://app.test dari pada http://localhost/app 901 = Aplikasi Anda akan mendapatkan url yang cantik ---> https://app.test dari pada https://localhost/app
902 = Tambhakan Sublime Text && Terminal ke Menu Klik Kanan 902 = Tambhakan Sublime Text && Terminal ke Menu Klik Kanan
903 = Cara cepat untuk membuka Editor Teks & Command Prompt 903 = Cara cepat untuk membuka Editor Teks & Command Prompt
904 = Lihat file README 904 = Lihat file README

View File

@@ -250,7 +250,7 @@ date: 20160821
# Setup # Setup
900=Laragon gira estremamente veloce e occupa poco spazio di memoria (< 4 MB) 900=Laragon gira estremamente veloce e occupa poco spazio di memoria (< 4 MB)
901=La tua app avrà una pretty url ---> http://app.test 901=La tua app avrà una pretty url ---> https://app.test
902=Aggiungi Sublime Text && Terminale al menu contestuale 902=Aggiungi Sublime Text && Terminale al menu contestuale
903=Avvio veloce per aprire Text Editor & Command Prompt 903=Avvio veloce per aprire Text Editor & Command Prompt
904=Mostra il file README 904=Mostra il file README

View File

@@ -250,7 +250,7 @@ date: 20181016
# Setup # Setup
900 = Laragonは、ほんの少しのメモリ消費でとても軽快に走ります (< 4 MB) 900 = Laragonは、ほんの少しのメモリ消費でとても軽快に走ります (< 4 MB)
901 = あなたのアプリはとても愛らしいURLになりますよ ---> http://app.test 901 = あなたのアプリはとても愛らしいURLになりますよ ---> https://app.test
902 = 右クリックメニューにSublime Text && Terminalを追加する 902 = 右クリックメニューにSublime Text && Terminalを追加する
903 = テキストエディタとコマンドプロンプトを開く簡単な方法 903 = テキストエディタとコマンドプロンプトを開く簡単な方法
904 = README ファイルを見る 904 = README ファイルを見る

View File

@@ -250,7 +250,7 @@ date: 20181016
# Setup # Setup
900 = 라라곤은 매우 빠르게 실행되며 메모리 사용량이 매우 적습니다 (< 4MB) 900 = 라라곤은 매우 빠르게 실행되며 메모리 사용량이 매우 적습니다 (< 4MB)
901 = 당신의 앱은 http://localhost/app 대신에 예쁜 url을 얻을 것입니다 ---> http://app.test 901 = 당신의 앱은 https://localhost/app 대신에 예쁜 url을 얻을 것입니다 ---> https://app.test
902 = 오른쪽 클릭 메뉴에 서브라임 에디터 및 터미널 추가 902 = 오른쪽 클릭 메뉴에 서브라임 에디터 및 터미널 추가
903 = 텍스트 편집기 및 명령 프롬프트를 여는 빠른 방법 903 = 텍스트 편집기 및 명령 프롬프트를 여는 빠른 방법
904 = README 파일보기 904 = README 파일보기

View File

@@ -249,7 +249,7 @@ date: 20181123
# Setup # Setup
900 = Laragon berjalan dengan sangat pantas dan mempunyai jejak memori yang sangat rendah (< 4 MB) 900 = Laragon berjalan dengan sangat pantas dan mempunyai jejak memori yang sangat rendah (< 4 MB)
901 = Apl anda akan mendapat url cantik ---> http://app.test 901 = Apl anda akan mendapat url cantik ---> https://app.test
902 = Tambah Sublime Text && Terminal ke Menu Klik-Kanan 902 = Tambah Sublime Text && Terminal ke Menu Klik-Kanan
903 = Cara pantas untuk buka Editor Teks & Arahan Prompt 903 = Cara pantas untuk buka Editor Teks & Arahan Prompt
904 = Papar fail BACASAYA 904 = Papar fail BACASAYA

View File

@@ -250,7 +250,7 @@ Dato: 26.06.2017
# Setup # Setup
900=Laragon kjører ekstremt fort og har svært lavt minnefottrykk (<4 MB) 900=Laragon kjører ekstremt fort og har svært lavt minnefottrykk (<4 MB)
901=Appen din vil få normal url ---> http://app.test 901=Appen din vil få normal url ---> https://app.test
902=Legg til Sublime Text && Terminal til Høyreklikk-menyen 902=Legg til Sublime Text && Terminal til Høyreklikk-menyen
903=Rask måter å åpne tekstredigerer og kommandoprompt 903=Rask måter å åpne tekstredigerer og kommandoprompt
904=Se Lesemeg-filen 904=Se Lesemeg-filen

View File

@@ -251,7 +251,7 @@ date: 20250111
# Setup # Setup
900 = لاراگون بسیار سریع اجرا می شود و دارای ردپای کمی در حافظه میباشد (< 4 MB) 900 = لاراگون بسیار سریع اجرا می شود و دارای ردپای کمی در حافظه میباشد (< 4 MB)
901 = برنامه شما URL زیبا را دریافت می کند ---> http://app.test 901 = برنامه شما URL زیبا را دریافت می کند ---> https://app.test
902 = اضافه کردن Notepad++ و ترمینال به منوی راست کلیک 902 = اضافه کردن Notepad++ و ترمینال به منوی راست کلیک
903 = راه های سریع برای باز کردن ویرایشگر متن و خط فرمان 903 = راه های سریع برای باز کردن ویرایشگر متن و خط فرمان
904 = فایل READMe را مشاهده کنید 904 = فایل READMe را مشاهده کنید

View File

@@ -1,6 +1,6 @@
-------------------------------------------------------- --------------------------------------------------------
version: 2.0.4 version: 2.0.4
author: Błażej Hap - blazejhap@gmail.com - http://conit-group.pl author: Błażej Hap - blazejhap@gmail.com - https://conit-group.pl
modified by: Manam modified by: Manam
date: 20160802 date: 20160802
-------------------------------------------------------- --------------------------------------------------------
@@ -250,7 +250,7 @@ date: 20160802
# Setup # Setup
900=Laragon działa ekstremalnie szybko i zajmuje bardzo mało pamięci (< 4 MB) 900=Laragon działa ekstremalnie szybko i zajmuje bardzo mało pamięci (< 4 MB)
901=Twoja aplikacja będzie dostępna pod wygodnym adresem ---> http://app.test 901=Twoja aplikacja będzie dostępna pod wygodnym adresem ---> https://app.test
902=Dodaj 'Sublime Text' i 'Terminal' do menu pod prawm klawiszem myszy 902=Dodaj 'Sublime Text' i 'Terminal' do menu pod prawm klawiszem myszy
903=Szybki sposób, aby otworzyć 'Edytor tekstu' i 'Wiersz poleceń' 903=Szybki sposób, aby otworzyć 'Edytor tekstu' i 'Wiersz poleceń'
904=Pokaż plik README 904=Pokaż plik README

View File

@@ -236,7 +236,7 @@ date: 20190729
# Setup # Setup
900 = Laragon é executado extremamente rápido e tem um rasto na memória muito baixa (<4 MB) 900 = Laragon é executado extremamente rápido e tem um rasto na memória muito baixa (<4 MB)
901 = Seu aplicativo receberá um URL bonito ---> http://app.test 901 = Seu aplicativo receberá um URL bonito ---> https://app.test
902 = Adicionar texto sublime && Terminal ao menu do botão direito 902 = Adicionar texto sublime && Terminal ao menu do botão direito
903 = Formas rápidas de abrir o Editor de Texto e o Prompt de Comando 903 = Formas rápidas de abrir o Editor de Texto e o Prompt de Comando
904 = Visualizar o arquivo README 904 = Visualizar o arquivo README

View File

@@ -250,7 +250,7 @@ date: 20191215
# Установка # Установка
900 = Laragon работает очень быстро и имеет очень низкий объем памяти (менее 4 МБ) 900 = Laragon работает очень быстро и имеет очень низкий объем памяти (менее 4 МБ)
901 = Ваше приложение получит удобный URL ---> http://app.test 901 = Ваше приложение получит удобный URL ---> https://app.test
902 = Добавить Sublime Text и Терминал в контекстное меню Windows 902 = Добавить Sublime Text и Терминал в контекстное меню Windows
903 = Быстрый способ открыть текстовый редактор и командную строку 903 = Быстрый способ открыть текстовый редактор и командную строку
904 = Посмотреть файл README 904 = Посмотреть файл README

View File

@@ -250,7 +250,7 @@ date: 20200801
# Nastavitve # Nastavitve
900 = Laragon deluje zelo hitro in ima zelo nizko rabo pomnilnika (<4 MB) 900 = Laragon deluje zelo hitro in ima zelo nizko rabo pomnilnika (<4 MB)
901 = Vaša aplikacija bo dobila lep URL ---> http://app.test 901 = Vaša aplikacija bo dobila lep URL ---> https://app.test
902 = Dodaj Sublime Text && Terminal na kontekstualni meni desnega klika 902 = Dodaj Sublime Text && Terminal na kontekstualni meni desnega klika
903 = Hitri načini za odpiranje urejevalnika besedil in ukazne vrstice (Command Prompt) 903 = Hitri načini za odpiranje urejevalnika besedil in ukazne vrstice (Command Prompt)
904 = Ogled datoteke README 904 = Ogled datoteke README

View File

@@ -250,7 +250,7 @@ date: 20200527
# Setup # Setup
900 = Laragon Körs och är extremt snabb,har mycket lågt minnesavtryck (< 4 MB) 900 = Laragon Körs och är extremt snabb,har mycket lågt minnesavtryck (< 4 MB)
901 = Din app kommer få vackra länkar ---> http://app.test 901 = Din app kommer få vackra länkar ---> https://app.test
902 = Lägg Sublime Text && Terminal till högerklickmenyn 902 = Lägg Sublime Text && Terminal till högerklickmenyn
903 = Snabbt sätt att öppna Text Editor och Command Prompt 903 = Snabbt sätt att öppna Text Editor och Command Prompt
904 = Visa README-filen 904 = Visa README-filen

View File

@@ -251,7 +251,7 @@ date: 20191013
# Setup # Setup
900 = Laragon son derece hızlı çalışır ve çok az bellek kaplar (< 4 MB) 900 = Laragon son derece hızlı çalışır ve çok az bellek kaplar (< 4 MB)
901 = Uygulama adresleriniz ---> http://app.test 901 = Uygulama adresleriniz ---> https://app.test
902 = Sağ tıklama menüse Sublime Text ve Terminal ekle 902 = Sağ tıklama menüse Sublime Text ve Terminal ekle
903 = Metin Düzenleyici ve Komut İstemi'ni açmanın hızlı yolları 903 = Metin Düzenleyici ve Komut İstemi'ni açmanın hızlı yolları
904 = Benioku dosyasını görüntüle 904 = Benioku dosyasını görüntüle

View File

@@ -251,7 +251,7 @@ date: 20170703
# Setup # Setup
900 = Laragon дуже швидко працює та споживає дуже мало оперативної пам`яті (< 4 MB) 900 = Laragon дуже швидко працює та споживає дуже мало оперативної пам`яті (< 4 MB)
901 = Ваш додаток отримає гарний URL ---> http://app.test 901 = Ваш додаток отримає гарний URL ---> https://app.test
902 = Додати Sublime Text && Terminal в контекстне меню правою кнопкою мишки 902 = Додати Sublime Text && Terminal в контекстне меню правою кнопкою мишки
903 = Швидкі методи відкрити Текстовий Редактор & Командний Рядок 903 = Швидкі методи відкрити Текстовий Редактор & Командний Рядок
904 = Переглянути README файл 904 = Переглянути README файл

View File

@@ -70,7 +70,7 @@ date: 20160919
320=Click để thay đổi thư mục chứa dữ liệu của MySQL 320=Click để thay đổi thư mục chứa dữ liệu của MySQL
322=Tự động tạo host ảo 322=Tự động tạo host ảo
323=Đưa thư mục <name> vào Document Root, Laragon sẽ tạo link đẹp cho bạn --> http://name.test 323=Đưa thư mục <name> vào Document Root, Laragon sẽ tạo link đẹp cho bạn --> https://name.test
# %s for a string placeholder # %s for a string placeholder
324=Định dạng 324=Định dạng
@@ -252,7 +252,7 @@ date: 20160919
# Setup # Setup
900=Laragon chạy cực nhanh và dùng rất ít bộ nhớ (< 4 MB) 900=Laragon chạy cực nhanh và dùng rất ít bộ nhớ (< 4 MB)
901=app của bạn sẽ có link đẹp ---> http://app.test 901=app của bạn sẽ có link đẹp ---> https://app.test
902=Thêm Sublime Text && Terminal vào Menu Phải 902=Thêm Sublime Text && Terminal vào Menu Phải
903=Giúp bạn mở trình soạn thảo và gõ lệnh nhanh chóng 903=Giúp bạn mở trình soạn thảo và gõ lệnh nhanh chóng
904=Xem README 904=Xem README

File diff suppressed because one or more lines are too long

View File

@@ -1,198 +0,0 @@
Change Log
============================
### Version 2.0 ###
SimpleAjaxUploader.js:
* Added support for drag and drop file uploads
* Added `ss.uploadSetup()` method to set default uploader option values (useful for multiple uploader instances)
* Added `noParams` option to disable the default behavior of appending the file name to the URL query string
* Numerous code improvements throughout -- bug fixes, memory usage, etc.
Uploader.php
* Refactored into a single class in accordance with one class, one file
* Made improvements to error detection and handling
* Added support for reading the `X-File-Name` header as an alternative to query string parameters for sending file names to the server
* Set default value of the `$uploadName` property to be `"uploadfile"` for consistency with the examples - <a href="https://github.com/LPology/Simple-Ajax-Uploader/issues/72">72</a>
### Version 1.11 ###
* Added support for PHP Session Upload Progress for PHP 5.4+ (APC was deprecated in 5.3)
* Added `clearQueue()` method which gives the user the ability to clear all files in queue - <a href="https://github.com/LPology/Simple-Ajax-Uploader/pull/62">#62</a> - (Special thanks to <a href="https://github.com/mouse0270">mouse0270</a> for this one)
* Fixed multiple file selection bug - <a href="https://github.com/LPology/Simple-Ajax-Uploader/pull/67">#67</a> - (Special thanks to <a href="https://github.com/genintho">genintho</a> for this)
* Fixed bug which could allow form/input elements to be created with invalid name/ID attributes in IE7-9
### Version 1.10.1 ###
* `iframe` and `form` elements are now created with `document.createElement()` rather than the much slower HTML injection method
* Removed unused variable from `_uploadIframe()`
### Version 1.10 ###
* Added `setOptions()` method for setting or changing upload options - <a href="https://github.com/LPology/Simple-Ajax-Uploader/issues/54">#54</a> - (special thanks to <a href="https://github.com/hauru">hauru</a> for this)
* Added `customHeader` option for sending custom request headers - <a href="https://github.com/LPology/Simple-Ajax-Uploader/issues/47">#47</a> (special thanks to <a href="https://github.com/cillosis">cillosis</a> for this)
* Updated `ss.parseJSON()` to use a more secure method of manually parsing JSON
### Version 1.9.1 ###
* `onError()` callback now receives server response as an argument, if it exists, or `false` if it does not - <a href="https://github.com/LPology/Simple-Ajax-Uploader/pull/37">#37</a> (special thanks to <a href="https://github.com/KSDaemon">KSDaemon</a> for this)
<br />
<br />
<strong>API Change Note:</strong> For consistency with the other callbacks, the server response is passed to `onError()` as the next to last argument, directly before the upload button. Therefore, if you use the upload button parameter in `onError()`, you will need to update your code when upgrading.
<br />
<br />
* Switched from Google Closure Compiler to YUI Compressor for minification
### Version 1.9 ###
* Added CORS support - <a href="http://www.lpology.com/code/ajaxuploader/How-to-Cross-Domain-File-Uploading.php">Learn more</a>
* Query string parameters for Nginx Upload Progress Module in `_uploadIframe()` are now encoded with `encodeURIComponent()`
* Upload progress ID keys are now generated prior to each upload instead of on page load
* Query string parameters passed to `url` are now preserved - <a href="https://github.com/LPology/Simple-Ajax-Uploader/issues/34">#34</a> (special thanks to <a href="https://github.com/Deefjuh">Deefjuh</a> for this)
### Version 1.8.2 ###
* A reference to the button which triggers an upload is now passed as the last argument to the following callbacks: `onAbort()`, `onChange()`, `onSubmit()`, `onComplete()`, `onError()`, `startXHR()`, `endXHR()`, `startNonXHR()`, `endNonXHR()` (can be useful when using multiple upload buttons)
* Fixed bug which caused some methods to not work if called inside of `startXHR()` or `startNonXHR()`
* Fixed bug causing undefined variable in IE9 and older if `progressUrl` and `nginxProgressUrl` are not set
### Version 1.8.1 ###
* Added `destroy()` method for completely removing upload functionality
* Removed redundant call to `ss.verifyElem()` inside of `rerouteClicks()`
* Moved browser-specific checks to top of IIFE, as they only need to execute once
### Version 1.8 ###
SimpleAjaxUploader.js:
* Added support for <a href="http://wiki.nginx.org/HttpUploadProgressModule">Nginx Upload Progress Module</a>
* Added `setAbortBtn()` method to designate an element as "cancel" button
* Added `onAbort()` callback function to specify behavior upon manual abort
* Added `setPctBox()` method to designate an element to be injected with upload progress percentage
* Switched to a unique ID function that is RFC 4122 version 4 compliant
* The `button` option now accepts either a single button (element ID string, element, or jQuery object), or an array of buttons. If an array is passed, each element in the array will work as an upload button
* Upload progress update request keys are now locally generated
* Fixed bug that was causing `onError()` to be fired twice
* For consistency with jQuery behavior, any 2xx status code is now handled as a successful response (previously, only `200` and `201` were successful)
* Upload buttons are now being properly disabled/enabled at correct points
* Made significant improvements to error handling, particularly with iframe uploads and retrieving server provided progress updates
* Fixed a number of potential memory leaks for Internet Explorer
* Regular expressions are now pre-compiled and cached for better performance
* For server progress tracking, `sizeBox` and `onUpdateFileSize()` are no longer pointlessly set/called again after first progress update is received
uploadProgress.php:
* Removed functionality for returning upload keys, as RFC 4122 v4 compliant UUIDs are now generated client side
### Version 1.7 ###
SimpleAjaxUploader.js:
* Fixed IE6/IE7 memory leak when removing elements without first removing event listeners (<a href="https://github.com/LPology/Simple-Ajax-Uploader/issues/21">issue #21</a>)
* Fixed possible race condition in which `removeCurrent()` could potentially delete the wrong file from the upload queue
* Multiple file inputs are now disabled in Safari due to a browser bug that just screws everything up (see: http://stackoverflow.com/q/7231054/1091949)
* Switched to a smaller, faster process for cross-browser bounding box calculation
* Updated to faster methods of checking for, adding, and removing element CSS classes
* Combined `_checkExtension()` with `_checkFile()` to eliminate a function call/reduce code size
* Combined `_handleIframeResponse()` with `_uploadIframe()` and switched to a more efficient method of getting iframe contents
* Removed a number of unnecessary/redundant function calls, along with some unnecessary variable copying
* Updated `ss.verifyElem()` to use the much faster `charAt()` and `substr()` in place of a regex and `slice()`
* Added separate feature detection for file input `accept` attribute
Uploader.php:
* Removed unnecessary check of `$allowedExtensions` for `null` value in `handleUpload()`
* Added `final` keyword to `FileUploadXHR` and `FileUploadPOSTForm` classes and their respective methods to discourage direct use
### Version 1.6.5 ###
* When using `multipart`, additional data will now also appended to the multipart form.
* Cleaned up some messy code -- organization, unnecessary variable copying, etc.
### Version 1.6.4 ###
* Switched from using `setAttribute` to dot notation for setting element properties (some versions of IE don't handle `setAttribute` well)
* `ss.removeItem()` now uses the faster countdown method to loop through arrays
* In accordance with W3 standards, `_uploadXhr()` now accepts either a `200 OK` or `201 Created` as a successful response
* Uploader.php -- the `handleUpload()` method now checks whether the `allowedExtensions` property is `empty` instead of `null`. This prevents an "Invalid file type" error resulting from passing an empty array
### Version 1.6.3 ###
* Fixed bug which allowed `onComplete()` to be called after JSON parse error
### Version 1.6.2 ###
* Overhauled error handling to fix a number of issues.
* Added consistent error types for `onError()` so that the second parameter will be either:
`parseerror` (bad JSON from server), `transfererror` (xfer error during XHR upload), `servererror` (server response not `200 OK`)
* Fixed problem with null file size parameter for `endXHR()` callback
### Version 1.6.1 ###
* Plugin is now wrapped in an IIFE
* Leading semicolon added to close any previous statement
* Code is now in strict mode
* Cleaned up a few messy areas
### Version 1.6 ###
If the 1.6 release has a theme, it is flexibility. Nearly every update in this release is intended to allow greater flexibility for developers.
* Submitting a file which exceeds `maxSize` or is not an `allowedExtension` no longer triggers an alert, but will instead fire a callback
* Added `onSizeError()` callback function which fires when a file exceeds the `maxSize` option, if it is set
* Added `onExtError()` callback which fires when a file is not permitted by the `allowedExtensions` option, if it is set
* Removed `messages` option and `_errorMsg()`, both of which are no longer used
* Added new `accept` option, the value of which will be the value of the `accept` file input attribute in supporting browsers. <a href="http://stackoverflow.com/a/10503561/1091949">More info.</a>
* Added new `method` option to allow specifying an HTTP method other than POST
Special thanks to <a href="https://github.com/dleffler">dleffler</a>, <a href="https://github.com/devtrends">devtrends</a> and <a href="https://github.com/urcadox">urcadox</a> for their ideas and feedback.
### Version 1.5.3 ###
* Added `autoSubmit` check before submitting in `_cycleQueue()`
* Added check to ensure upload progress server key doesn't exceed 57 characters (max allowable APC key length)
* `rerouteClicks(element)` can now be used to add additional elements which can be clicked to open file box
### Version 1.5.2 ###
(This isn't as much a release as it is a signal to update for anyone who may have downloaded version 1.5.1 in the past few hours)
* Fixed "bug" from 1.5.1 that broke uploader without multiple option enabled
* Added `queue` option to disable automatic file queuing
### Version 1.5.1 ###
* Multiple file inputs are now used in browsers with support for File API, thus allowing multiple file selection if `multiple` option is `true`
* Removed some unnecessary variable copying
* Added queue system which allows files to be selected and automatically uploaded as others finish
* Added `getQueueSize()` function to get current number of files waiting in queue
* Fixed bug in which active upload counter was not properly updating when returning `false` from `startXHR()` and `startNonXHR()`
* Error messages now incorporate file names
### Version 1.5 ###
* Added support for multiple file uploading, along with Gmail-style multiple progress bars for tracking each file.
* Added new `maxSize` option for file size limits, `allowedExtensions` option for file type restrictions. Custom error messages supported for both.
* Updated `verifyElem()` to use a better method of detecting if an upload button is a jQuery object.
* Numerous code enhancements throughout - updated error handling, cleaner organization, performance improvements.
* Patched some memory leaks created by circular references in event handlers.
### Version 1.4.2 ###
* SimpleAjaxUploader.js - Added `multipart` option to allow multipart form upload instead of binary stream
* Uploader.php - The check for form uploads is now first in the constructor to accomodate new `multipart` option
* Uploader.php - Providing an array of valid file extensions is now optional. If not provided, all file types are allowed
* Added minified version of JS file
### Version 1.4.1 ###
* Fixed XHR status check logic that could allow false alarm calls to onError callback
* Removed redundant XHR status check
* Returning false from a callback no longer clears the file field. Not sure why it ever did to begin with.
* A status check now occurs prior to progress update requests to prevent potential loop that could be caused by a server error
* Parsing JSON in older browsers no longer uses `eval` because it's evil
### Version 1.4 ###
This release includes a major overhaul that adds functionality for implementing cross-browser upload progress support. Through feature detection and abstraction, it is now possible for the `onProgress` callback function to maintain consistent behavior across browsers.
Currently, only PHP (with APC extension) is supported. To use, set the newly added `progressUrl` option to the URL of the included UploadProgress.php script, and `onProgress` will then return upload progress data in Internet Explorer 9 and below.
Note that this added functionality does not affect the behavior of the plugin for those not using PHP, or just not using the feature.
For those not using PHP, a similar result can still be achieved with the `startXH`/`endXHR` and `startNonXHR`/`endNonXHR` callback functions, which are included specifically for defining behavior based on whether XHR uploads are supported.
Also, adding support for other programming languages would certainly be a welcome addition, if anyone is interested in working on that.
Other items:
* Added `onUpdateFileSize` callback function for getting file size in IE9 and below (When server supported progress is enabled)
* Removed the unneccessary _handleJSON method
* Added new ss.newXHR method
* Added extras folder for non-necessary items (i.e., everything but SimpleAjaxUploader.js)
* Adjusted request headers for XHR uploads
* Moved support detection for HTML5 File API to constructor so it only executes once
* Timestamps now appended to URLs to prevent browsers from caching requests
### Version 1.3 ###
* Returned to version numbering
* Updated method for parsing JSON
* Added PHP class for handling file uploads
* Cleaned up messy areas
### Earlier versions ###
Prior to version 1.3, I did a pretty horrible job of documenting changes, and, at one point, entirely dispensed with any notion of version control whatsoever. I have since seen the light.

View File

@@ -1,258 +0,0 @@
Simple Ajax Uploader
============================
A Javascript plugin for cross-browser Ajax file uploading. Supports drag and drop, CORS, and multiple file uploading with progress bars. Works in IE7-9, mobile, and all modern browsers.
```javascript
var uploader = new ss.SimpleUpload({
button: 'upload-btn', // HTML element used as upload button
url: '/PathTo/UploadHandler', // URL of server-side upload handler
name: 'uploadfile' // Parameter name of the uploaded file
});
```
### Features ###
* Cross-browser -- works in IE7+, Firefox, Chrome, Safari, Opera
* Supports multiple, concurrent file uploads (even in non-HTML5 browsers)
* Built-in CORS support
* Drag and drop file uploads (<strong>new in v2.0</strong>)
* No flash or external CSS -- a single 6Kb Javascript file (minified and gzipped)
* Progress bars in all browsers, including IE9 and older. Built-in support for:
* <a href="http://wiki.nginx.org/HttpUploadProgressModule">Nginx Upload Progress Module</a>
* <a href="http://www.php.net/manual/en/apc.configuration.php#ini.apc.rfc1867">PHP APC File Upload Progress</a>
* <a href="http://php.net/manual/en/session.upload-progress.php">PHP Session Upload Progress</a>
* Use any HTML element as the upload button
* No dependencies - use it with or without jQuery
* Provides individual callback functions for XHR-supported browsers and for browsers that do not support XHR uploads
* Ability to pass custom headers in request such as the Authorization header
### How to Use ###
<a href="https://www.lpology.com/code/ajaxuploader/">Live Demo</a><br />
<a href="https://www.lpology.com/code/ajaxuploader/docs.php">API Reference</a><br />
<a href="https://www.lpology.com/code/ajaxuploader/progress.php">Upload progress bars in IE9 (and older)</a><br />
<a href="https://www.lpology.com/code/ajaxuploader/How-to-Cross-Domain-File-Uploading.php">CORS &mdash; Cross-domain file uploading with Simple Ajax Uploader</a>
There are two main ways to use the plugin:
<strong>1. Single file uploading</strong> - Only one upload allowed at a time. Progress bar is an element that is re-used for each upload.<br />
<strong>2. Multiple file uploading</strong> - Allow multiple, concurrent file uploads. Progress bars are created on the fly before each upload.
#### Method 1: Single file uploading (one file at a time) ####
Before each upload, in the `onSubmit()` callback function, the on-page <code>sizeBox</code> and <code>progress</code> elements are assigned specific roles using these two functions:
`setProgressBar(elem)` - Designates an element as the progress bar for an upload.<br />
`setFileSizeBox(elem)` - Designates an element as the container in which the file size of an uploading file will be inserted.
As a result, when an upload begins, the file size of the upload is inserted into the <code>sizeBox</code> element and the CSS width of the <code>progress</code> element is set to 0%. As the upload progresses, the CSS width percentage of the <code>progress</code> element will be updated accordingly.
This approach of assigning roles to elements provides developers with a great deal of flexibility -- progress indicators can be styled in any way and placed anywhere on the page.
```javascript
var sizeBox = document.getElementById('sizeBox'), // container for file size info
progress = document.getElementById('progress'); // the element we're using for a progress bar
var uploader = new ss.SimpleUpload({
button: 'uploadButton', // file upload button
url: 'uploadHandler.php', // server side handler
name: 'uploadfile', // upload parameter name
progressUrl: 'uploadProgress.php', // enables cross-browser progress support (more info below)
responseType: 'json',
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'],
maxSize: 1024, // kilobytes
hoverClass: 'ui-state-hover',
focusClass: 'ui-state-focus',
disabledClass: 'ui-state-disabled',
onSubmit: function(filename, extension) {
this.setFileSizeBox(sizeBox); // designate this element as file size container
this.setProgressBar(progress); // designate as progress bar
},
onComplete: function(filename, response) {
if (!response) {
alert(filename + 'upload failed');
return false;
}
// do something with response...
}
});
```
#### Method 2: Multiple file uploads ####
Below is an example of how to implement multiple file uploading with progress bars. A new progress bar is created for each file upload within the `onSubmit()` callback function.
Like in Method 1, the newly created elements are assigned roles using the `setProgressBar()` and `setFileSizeBox()` functions. Unlike the previous example, however, the progress elements are automatically removed when the upload is completed.
```javascript
var uploader = new ss.SimpleUpload({
button: 'uploadButton',
url: 'uploadHandler.php', // server side handler
progressUrl: 'uploadProgress.php', // enables cross-browser progress support (more info below)
responseType: 'json',
name: 'uploadfile',
multiple: true,
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'], // for example, if we were uploading pics
hoverClass: 'ui-state-hover',
focusClass: 'ui-state-focus',
disabledClass: 'ui-state-disabled',
onSubmit: function(filename, extension) {
// Create the elements of our progress bar
var progress = document.createElement('div'), // container for progress bar
bar = document.createElement('div'), // actual progress bar
fileSize = document.createElement('div'), // container for upload file size
wrapper = document.createElement('div'), // container for this progress bar
progressBox = document.getElementById('progressBox'); // on page container for progress bars
// Assign each element its corresponding class
progress.className = 'progress';
bar.className = 'bar';
fileSize.className = 'size';
wrapper.className = 'wrapper';
// Assemble the progress bar and add it to the page
progress.appendChild(bar);
wrapper.innerHTML = '<div class="name">'+filename+'</div>'; // filename is passed to onSubmit()
wrapper.appendChild(fileSize);
wrapper.appendChild(progress);
progressBox.appendChild(wrapper); // just an element on the page to hold the progress bars
// Assign roles to the elements of the progress bar
this.setProgressBar(bar); // will serve as the actual progress bar
this.setFileSizeBox(fileSize); // display file size beside progress bar
this.setProgressContainer(wrapper); // designate the containing div to be removed after upload
},
// Do something after finishing the upload
// Note that the progress bar will be automatically removed upon completion because everything
// is encased in the "wrapper", which was designated to be removed with setProgressContainer()
onComplete: function(filename, response) {
if (!response) {
alert(filename + 'upload failed');
return false;
}
// Stuff to do after finishing an upload...
}
});
```
For multiple file uploads, we use an additional function: `setProgressContainer(elem)`. This function designates an element to be removed from the DOM after the upload is completed.
In the example, the element set to be removed with `setProgressContainer()` is the outer container for the progress elements. As a result, progress bars will be removed from the DOM after each upload is completed.
### Cross-Browser Helper Functions ###
To ease the pain of supporting older browsers, the plugin includes a set of callback functions which allow specific behavior to be defined based on whether the user's browser supports XHR uploads/HTML5 File API:
<code>startXHR(filename, fileSize)</code> - Called prior to upload -- only in browsers that support XHR uploads<br />
<code>endXHR(filename)</code> - Called after upload is completed -- only in browsers that support XHR uploads<br />
<code>startNonXHR(filename)</code> - Called prior to upload -- only in browsers that <strong>do not</strong> support XHR uploads<br />
<code>endNonXHR(filename)</code> - Called after upload is completed -- only in browsers that <strong>do not</strong> support XHR uploads<br />
A common use case is to show an upload progress bar in browsers that support the <code>progress</code> event while displaying an animated GIF in older browsers:
```javascript
var progress = document.getElementById('progress'), // progress bar
loaderImg = document.getElementById('loaderImg'); // "loading" animated GIF
var uploader = new ss.SimpleUpload({
button: 'uploadButton',
url: 'uploadHandler.php', // server side handler
responseType: 'json',
name: 'uploadfile',
hoverClass: 'ui-state-hover',
focusClass: 'ui-state-focus',
disabledClass: 'ui-state-disabled',
startXHR: function(filename, size) {
progress.style.display = 'inline-block'; // show progress bar
this.setProgressBar(progress); // designate as progress bar
},
endXHR: function(filename) {
progress.style.display = 'none'; // hide progress bar
},
startNonXHR: function(filename) {
loaderImg.style.display = 'inline-block'; // show animated GIF
},
endNonXHR: function(filename) {
loaderImg.style.display = 'none'; // hide animated GIF
}
});
```
Returning <code>false</code> from <code>startXHR()</code> and <code>startNonXHR()</code> will prevent the upload from starting, just as it does with <code>onSubmit()</code> and <code>onChange()</code>.
### Server-side file handling ###
Files are uploaded by POST as either raw form data or regular multipart/form-data, depending on the browser.
### Using Uploader.php ###
<strong>Note:</strong> This PHP class is included only for convenience. <strong>It is not required to use PHP with Simple Ajax Uploader.</strong> The plugin is agnostic to server configuration, so use any language you prefer.
```php
<?php
require('Uploader.php');
$upload_dir = '/img_uploads/';
$valid_extensions = array('gif', 'png', 'jpeg', 'jpg');
$Upload = new FileUpload('uploadfile');
$result = $Upload->handleUpload($upload_dir, $valid_extensions);
if (!$result) {
echo json_encode(array('success' => false, 'msg' => $Upload->getErrorMsg()));
} else {
echo json_encode(array('success' => true, 'file' => $Upload->getFileName()));
}
```
You can also save the uploaded file with a different name by setting the `newFileName` property:
```php
$Upload = new FileUpload('uploadfile');
$ext = $Upload->getExtension(); // Get the extension of the uploaded file
$Upload->newFileName = 'customFileName.'.$ext;
$result = $Upload->handleUpload($upload_dir, $valid_extensions);
```
To access the newly uploaded file, use the `getSavedFile()` method to get the file's path after the upload is completed:
```php
$Upload = new FileUpload('uploadfile');
$result = $Upload->handleUpload($upload_dir, $valid_extensions);
if ($result) {
$path = $Upload->getSavedFile();
$imgsize = getimagesize($path);
// image resizing stuff...
}
```
### Passing Custom Headers ###
```javascript
var uploader = new ss.SimpleUpload({
customHeaders: {'Authorization': 'my-access-token'},
...
});
```
### Drag and Drop ###
Enable drag and drop uploading by passing an element to the `dropzone` option to serve as the drop zone:
```javascript
var uploader = new ss.SimpleUpload({
dropzone: 'dragbox', // ID of element to be the drop zone
url: 'uploadHandler.php',
name: 'uploadfile',
responseType: 'json',
onComplete: function(filename, response) {
// do something with response...
}
});
```
### License ###
Released under the MIT license.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,254 +0,0 @@
<?php
/**
* Simple Ajax Uploader
* Version 2.0
* https://github.com/LPology/Simple-Ajax-Uploader
*
* Copyright 2012-2015 LPology, LLC
* Released under the MIT license
*
* View the documentation for an example of how to use this class.
*/
class FileUpload {
private $fileName; // Filename of the uploaded file
private $fileSize; // Size of uploaded file in bytes
private $fileExtension; // File extension of uploaded file
private $fileNameWithoutExt;
private $savedFile; // Path to newly uploaded file (after upload completed)
private $errorMsg; // Error message if handleUpload() returns false (use getErrorMsg() to retrieve)
private $isXhr;
public $uploadDir; // File upload directory (include trailing slash)
public $allowedExtensions; // Array of permitted file extensions
public $sizeLimit = 10485760; // Max file upload size in bytes (default 10MB)
public $newFileName; // Optionally save uploaded files with a new name by setting this
public $corsInputName = 'XHR_CORS_TARGETORIGIN';
public $uploadName = 'uploadfile';
function __construct($uploadName = null) {
if ($uploadName !== null) {
$this->uploadName = $uploadName;
}
if (isset($_FILES[$this->uploadName])) {
$this->isXhr = false;
if ($_FILES[$this->uploadName]['error'] === UPLOAD_ERR_OK) {
$this->fileName = $_FILES[$this->uploadName]['name'];
$this->fileSize = $_FILES[$this->uploadName]['size'];
} else {
$this->setErrorMsg($this->errorCodeToMsg($_FILES[$this->uploadName]['error']));
}
} elseif (isset($_SERVER['HTTP_X_FILE_NAME']) || isset($_GET[$this->uploadName])) {
$this->isXhr = true;
$this->fileName = isset($_SERVER['HTTP_X_FILE_NAME']) ?
$_SERVER['HTTP_X_FILE_NAME'] : $_GET[$this->uploadName];
if (isset($_SERVER['CONTENT_LENGTH'])) {
$this->fileSize = (int)$_SERVER['CONTENT_LENGTH'];
} else {
throw new Exception('Content length is empty.');
}
}
if ($this->fileName) {
$pathinfo = pathinfo($this->fileName);
if (array_key_exists('extension', $pathinfo) &&
array_key_exists('filename', $pathinfo))
{
$this->fileExtension = strtolower($pathinfo['extension']);
$this->fileNameWithoutExt = $pathinfo['filename'];
}
}
}
public function getFileName() {
return $this->fileName;
}
public function getFileSize() {
return $this->fileSize;
}
public function getExtension() {
return $this->fileExtension;
}
public function getErrorMsg() {
return $this->errorMsg;
}
public function getSavedFile() {
return $this->savedFile;
}
private function errorCodeToMsg($code) {
switch($code) {
case UPLOAD_ERR_INI_SIZE:
$message = 'File size exceeds limit.';
break;
case UPLOAD_ERR_PARTIAL:
$message = 'The uploaded file was only partially uploaded.';
break;
case UPLOAD_ERR_NO_FILE:
$message = 'No file was uploaded.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$message = 'Missing a temporary folder.';
break;
case UPLOAD_ERR_CANT_WRITE:
$message = 'Failed to write file to disk.';
break;
case UPLOAD_ERR_EXTENSION:
$message = 'File upload stopped by extension.';
break;
default:
$message = 'Unknown upload error.';
break;
}
return $message;
}
private function checkExtension($ext, $allowedExtensions) {
if (!is_array($allowedExtensions))
return false;
if (!in_array(strtolower($ext), array_map('strtolower', $allowedExtensions)))
return false;
return true;
}
private function setErrorMsg($msg) {
if (empty($this->errorMsg))
$this->errorMsg = $msg;
}
private function fixDir($dir) {
if (empty($dir))
return $dir;
$slash = DIRECTORY_SEPARATOR;
$dir = str_replace('/', $slash, $dir);
$dir = str_replace('\\', $slash, $dir);
return substr($dir, -1) == $slash ? $dir : $dir . $slash;
}
// escapeJS and jsMatcher are adapted from the Escaper component of
// Zend Framework, Copyright (c) 2005-2013, Zend Technologies USA, Inc.
// https://github.com/zendframework/zf2/tree/master/library/Zend/Escaper
private function escapeJS($string) {
return preg_replace_callback('/[^a-z0-9,\._]/iSu', $this->jsMatcher, $string);
}
private function jsMatcher($matches) {
$chr = $matches[0];
if (strlen($chr) == 1)
return sprintf('\\x%02X', ord($chr));
if (function_exists('iconv'))
$chr = iconv('UTF-16BE', 'UTF-8', $chr);
elseif (function_exists('mb_convert_encoding'))
$chr = mb_convert_encoding($chr, 'UTF-8', 'UTF-16BE');
return sprintf('\\u%04s', strtoupper(bin2hex($chr)));
}
public function corsResponse($data) {
if (isset($_REQUEST[$this->corsInputName])) {
$targetOrigin = $this->escapeJS($_REQUEST[$this->corsInputName]);
$targetOrigin = htmlspecialchars($targetOrigin, ENT_QUOTES, 'UTF-8');
return "<script>window.parent.postMessage('$data','$targetOrigin');</script>";
}
return $data;
}
private function saveXhr($path) {
if (false !== file_put_contents($path, fopen('php://input', 'r')))
return true;
return false;
}
private function saveForm($path) {
if (move_uploaded_file($_FILES[$this->uploadName]['tmp_name'], $path))
return true;
return false;
}
private function save($path) {
if (true === $this->isXhr)
return $this->saveXhr($path);
return $this->saveForm($path);
}
public function handleUpload($uploadDir = null, $allowedExtensions = null) {
if (!$this->fileName) {
$this->setErrorMsg('Incorrect upload name or no file uploaded');
return false;
}
if ($this->fileSize == 0) {
$this->setErrorMsg('File is empty');
return false;
}
if ($this->fileSize > $this->sizeLimit) {
$this->setErrorMsg('File size exceeds limit');
return false;
}
if (!empty($uploadDir))
$this->uploadDir = $uploadDir;
$this->uploadDir = $this->fixDir($this->uploadDir);
if (!is_writable($this->uploadDir)) {
$this->setErrorMsg('Upload directory is not writable');
return false;
}
if (is_array($allowedExtensions))
$this->allowedExtensions = $allowedExtensions;
if (!empty($this->allowedExtensions)) {
if (!$this->checkExtension($this->fileExtension, $this->allowedExtensions)) {
$this->setErrorMsg('Invalid file type');
return false;
}
}
$this->savedFile = $this->uploadDir . $this->fileName;
if (!empty($this->newFileName)) {
$this->fileName = $this->newFileName;
$this->savedFile = $this->uploadDir . $this->fileName;
$this->fileNameWithoutExt = null;
$this->fileExtension = null;
$pathinfo = pathinfo($this->fileName);
if (array_key_exists('filename', $pathinfo))
$this->fileNameWithoutExt = $pathinfo['filename'];
if (array_key_exists('extension', $pathinfo))
$this->fileExtension = strtolower($pathinfo['extension']);
}
if (!$this->save($this->savedFile)) {
$this->setErrorMsg('File could not be saved');
return false;
}
return true;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,28 +0,0 @@
.container {
width: auto;
max-width: 680px;
padding: 0 15px;
}
.progress {
margin-bottom:0;
margin-top:6px;
margin-left:10px;
}
.btn.focus {
outline:thin dotted #333;
outline:5px auto -webkit-focus-ring-color;
outline-offset:-2px;
}
.btn.hover {
color:#ffffff;
background-color:#3276b1;
border-color:#285e8e;
}
.highlight {
background-color: yellow;
font-weight: bold;
}

View File

@@ -1,34 +0,0 @@
<?php
/**
* Simple Ajax Uploader
* Version 2.0
* https://github.com/LPology/Simple-Ajax-Uploader
*
* Copyright 2012-2015 LPology, LLC
* Released under the MIT license
*
*/
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if (isset($_SERVER['REQUEST_METHOD'])) {
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
}
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}
exit;
}
}

View File

@@ -1,18 +0,0 @@
<?php
require('Uploader.php');
// Directory where we're storing uploaded images
// Remember to set correct permissions or it won't work
$upload_dir = '../uploads';
$uploader = new FileUpload('uploadfile');
$uploader->sizeLimit = 1024*1024*1024; // Max file upload size in bytes 1GB)
// Handle the upload
$result = $uploader->handleUpload($upload_dir);
if (!$result) {
exit(json_encode(array('success' => false, 'msg' => $uploader->getErrorMsg())));
}
echo json_encode(array('success' => true));

View File

@@ -1,45 +0,0 @@
<?php
/**
* Simple Ajax Uploader
* Version 2.0
* https://github.com/LPology/Simple-Ajax-Uploader
*
* Copyright 2012-2015 LPology, LLC
* Released under the MIT license
*
* Returns upload progress updates for browsers that don't support the HTML5 File API.
* Falling back to this method allows for upload progress support across virtually all browsers.
* Requires PHP 5.4+
* Further documentation: http://php.net/manual/en/session.upload-progress.php
*
*/
session_start();
if (!isset($_POST[ini_get('session.upload_progress.name')])) {
exit(json_encode(array('success' => false)));
}
$key = ini_get('session.upload_progress.prefix') . $_POST[ini_get('session.upload_progress.name')];
if (!isset($_SESSION[$key])) {
exit(json_encode(array('success' => false)));
}
$progress = $_SESSION[$key];
$pct = 0;
$size = 0;
if (is_array($progress)) {
if (array_key_exists('bytes_processed', $progress) && array_key_exists('content_length', $progress)) {
if ($progress['content_length'] > 0) {
$pct = round(($progress['bytes_processed'] / $progress['content_length']) * 100);
$size = round($progress['content_length'] / 1024);
}
}
}
echo json_encode(array('success' => true, 'pct' => $pct, 'size' => $size));

View File

@@ -1,44 +0,0 @@
<?php
/**
* Simple Ajax Uploader
* Version 2.0
* https://github.com/LPology/Simple-Ajax-Uploader
*
* Copyright 2012-2015 LPology, LLC
* Released under the MIT license
*
* Returns upload progress updates for browsers that don't support the HTML5 File API.
* Falling back to this method allows for upload progress support across virtually all browsers.
*
*/
// This "if" statement is only necessary for CORS uploads -- if you're
// only doing same-domain uploads then you can delete it if you want
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
if (isset($_REQUEST['progresskey'])) {
$status = apc_fetch('upload_'.$_REQUEST['progresskey']);
} else {
exit(json_encode(array('success' => false)));
}
$pct = 0;
$size = 0;
if (is_array($status)) {
if (array_key_exists('total', $status) && array_key_exists('current', $status)) {
if ($status['total'] > 0) {
$pct = round(($status['current'] / $status['total']) * 100);
$size = round($status['total'] / 1024);
}
}
}
echo json_encode(array('success' => true, 'pct' => $pct, 'size' => $size));

View File

@@ -1,154 +0,0 @@
<?php
function formatLink($file) {
if (isset($_SERVER['HTTPS']) &&
($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$protocol = 'https';
} else {
$protocol = 'http';
}
$link = sprintf('%s://%s/laragon/uploads/%s', $protocol, $_SERVER['HTTP_HOST'], $file);
return sprintf('<a href="%s" target="_blank">%s</a>', $link, $link);
}
function listFiles() {
$upload_dir = dirname(__FILE__).'\uploads';
echo sprintf('<div>Files locate at: <b>%s</b></div>', $upload_dir);
if ($handle = opendir($upload_dir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
echo '<div>'.formatLink($entry).'</div>';
}
}
closedir($handle);
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Uploader</title>
<link href="extras/assets/css/bootstrap.min.css" rel="stylesheet">
<link href="extras/assets/css/styles.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row" style="padding-top:10px;">
<div class="col-xs-2">
<button id="uploadBtn" class="btn btn-large btn-primary">Choose Files</button>
</div>
<div class="col-xs-10">
<div id="progressOuter" class="progress progress-striped active" style="display:none;">
<div id="progressBar" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
</div>
</div>
</div>
</div>
<div class="row" style="padding-top:10px;">
<div class="col-xs-10">
<div id="msgBox">
</div>
<div id="uploadedFiles">
</div>
<p>
<hr />
<div>
<small>
<div><u>Tip</u>: Hold Shift if you want to upload multiple files.</div>
<div>If you want to share over the Internet, just run:</div>
<div><b><i>ngrok http 80</i></b></div>
</small>
</div>
<hr />
<div id="listFiles">
<?php
listFiles();
//$upload_dir = dirname(__FILE__).'\uploads';
//echo $upload_dir;
//echo '<a href="http://'.$_SERVER['HTTP_HOST'].'/laragon/uploads/" target="_blank">'.$_SERVER['HTTP_HOST'].'</a>';
?>
</div>
</p>
</div>
</div>
</div>
<script src="extras/SimpleAjaxUploader.min.js"></script>
<script>
function escapeTags( str ) {
return String( str )
.replace( /&/g, '&amp;' )
.replace( /"/g, '&quot;' )
.replace( /'/g, '&#39;' )
.replace( /</g, '&lt;' )
.replace( />/g, '&gt;' );
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
window.onload = function() {
var btn = document.getElementById('uploadBtn'),
progressBar = document.getElementById('progressBar'),
progressOuter = document.getElementById('progressOuter'),
msgBox = document.getElementById('msgBox');
listFiles = document.getElementById('listFiles');
theLink = '<?php echo formatLink('{{FILE}}'); ?>';
var uploader = new ss.SimpleUpload({
button: btn,
url: 'extras/file_upload.php',
name: 'uploadfile',
hoverClass: 'hover',
multiple: true,
focusClass: 'focus',
responseType: 'json',
startXHR: function() {
progressOuter.style.display = 'block'; // make progress bar visible
this.setProgressBar( progressBar );
},
onSubmit: function() {
msgBox.innerHTML = ''; // empty the message box
btn.innerHTML = 'Uploading...'; // change button text to "Uploading..."
},
onComplete: function( filename, response ) {
btn.innerHTML = 'Choose Files';
progressOuter.style.display = 'none'; // hide progress bar when upload is completed
if ( !response ) {
msgBox.innerHTML = 'Unable to upload file';
return;
}
if ( response.success === true ) {
msgBox.innerHTML = '<strong>' + escapeTags( filename ) + '</strong>' + ' successfully uploaded.';
uploadedFiles.innerHTML = '<div class="highlight">' + replaceAll(theLink, '{{FILE}}', filename) + '</div>' + uploadedFiles.innerHTML ;
} else {
if ( response.msg ) {
msgBox.innerHTML = escapeTags( response.msg );
} else {
msgBox.innerHTML = 'An error occurred and the upload failed.';
}
}
},
onError: function() {
progressOuter.style.display = 'none';
msgBox.innerHTML = 'Unable to upload file';
}
});
};
</script>
</body>
</html>

View File

@@ -1 +0,0 @@
Antony Dovgal, Mikael Johansson

View File

@@ -1,68 +0,0 @@
--------------------------------------------------------------------
The PHP License, Version 3.0
Copyright (c) 1999 - 2005 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes PHP, freely available from
<http://www.php.net/>".
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------
This software consists of voluntary contributions made by many
individuals on behalf of the PHP Group.
The PHP Group can be contacted via Email at group@php.net.
For more information on the PHP Group and the PHP project,
please see <http://www.php.net>.
This product includes the Zend Engine, freely available at
<http://www.zend.com>.

View File

@@ -1,149 +0,0 @@
memcached module for PHP
------------------------
This module requires zlib library, used for on-the-fly data (de)compression.
Also, you'll need memcached to use it =)
The memcached website is here:
http://www.danga.com/memcached/
You will probably need libevent to install memcached:
You can download it here: http://www.monkey.org/~provos/libevent/
How to run tests:
1. sh tests/memcache.sh
2. TEST_PHP_EXECUTABLE=/usr/local/bin/php php -dextension=modules/memcache.so run-tests.php -d extension=modules/memcache.so
New API in 3.0
------------------------
Version 3 introduces a new class "MemcachePool" which implements the new API, the
old class "Memcache" is still retained (but is deprecated) with the same interface
for backwards compatibility. Please note that you need a new memcached version to
use the CAS, default value to increment/decrement, append and prepend, and binary
protocol features.
New INI directives are available to allow control over protocol, redundancy and hash
strategy selection. These are
# The binary protocol results in less traffic and is more efficient
# for the client and server to generate/parse
memcache.protocol = {ascii, binary} # default ascii
# When enabled the client sends requests to N servers in parallel, resulting in
# a somewhat crude reduncancy or mirroring, suitable when used as a session
# storage.
#
# If data integrity is of greater importance a real replicating memcached
# backend such as "repcached" (http://sourceforge.net/projects/repcached/) is
# recommended
memcache.redundancy = <int> # default 1
memcache.session_redundancy = <int> # default 2
# Hash strategy and function selection. The consistent hashing strategy
# is now the default as it allows servers to be added and removed from
# the pool without resulting in all or most keys being re-mapped to
# other server (ie. voiding the cache)
memcache.hash_strategy = {standard, consistent} # default consistent
memcache.hash_function = {crc32, fnv} # default crc32
# Compression is enabled by default, the threshold which control the minimum
# string length which triggers compresssion can be changed as
memcache.compress_threshold = <int> # default 20000
The directives are used by the MemcachePool constructor so you can instantiate
several pools with different settings by using ini_set() creativly. For example
ini_set('memcache.protocol', 'binary');
$binarypool = new MemcachePool();
$binarypool->addServer(...)
ini_set('memcache.protocol', 'ascii');
ini_set('memcache.redundancy', '2');
$redundantpool = new MemcachePool();
$redundantpool->addServer(...)
ini_set('memcache.redundancy', '1');
The new interface looks like
class MemcachePool() {
bool connect(string host, int tcp_port = 11211, int udp_port = 0, bool persistent = true, int weight = 1, int timeout = 1, int retry_interval = 15)
bool addServer(string host, int tcp_port = 11211, int udp_port = 0, bool persistent = true, int weight = 1, int timeout = 1, int retry_interval = 15, bool status = true)
bool setServerParams(string host, int tcp_port = 11211, int timeout = 1, int retry_interval = 15, bool status = true)
/**
* Supports fetching flags and CAS values
*/
mixed get(mixed key, mixed &flags = null, mixed &cas = null)
/**
* Supports multi-set, for example
* $memcache->set(array('key1' => 'val1', 'key2' => 'val1'), null, 0, 60)
*/
bool add(mixed key, mixed var = null, int flag = 0, int exptime = 0)
bool set(mixed key, mixed var = null, int flag = 0, int exptime = 0)
bool replace(mixed key, mixed var = null, int flag = 0, int exptime = 0)
/**
* Compare-and-Swap, uses the CAS param from MemcachePool::get()
*/
bool cas(mixed key, mixed var = null, int flag = 0, int exptime = 0, int cas = 0)
/**
* Prepends/appends a value to an existing one
*/
bool append(mixed key, mixed var = null, int flag = 0, int exptime = 0)
bool prepend(mixed key, mixed var = null, int flag = 0, int exptime = 0)
/**
* Supports multi-key operations, for example
* $memcache->delete(array('key1', 'key2'))
*/
bool delete(mixed key, int exptime = 0)
/**
* Supports multi-key operations, for example
* $memcache->increment(array('key1', 'key2'), 1, 0, 0)
*
* The new defval (default value) and exptime (expiration time) are used
* if the key doesn't already exist. They must be supplied (even if 0) for
* this to be enabled.
*
* Returns an integer with the new value if key is a string
* Returns an array of integers if the key is an array
*/
mixed increment(mixed key, int value = 1, int defval = 0, int exptime = 0)
mixed decrement(mixed key, int value = 1, int defval = 0, int exptime = 0)
/**
* Assigns a pool-specific failure callback which will be called when
* a request fails. May be null in order to disable callbacks. The callback
* receive arguments like
*
* function mycallback($host, $tcp_port, $udp_port, $error, $errnum)
*
* Where $host and $error are strings or null, the other params are integers.
*/
bool setFailureCallback(function callback)
/**
* Locates the server a given would be hashed to
*
* Returns a string "hostname:port" on success
* Returns false on failure such as invalid key
*/
string findServer(string key)
}
Maintainers:
Herman J. Radtke III hradtke at php dot net

View File

@@ -1,24 +0,0 @@
<?php
$memcache = memcache_connect('localhost', 11211);
if ($memcache) {
$memcache->set("str_key", "String to store in memcached");
$memcache->set("num_key", 123);
$object = new StdClass;
$object->attribute = 'test';
$memcache->set("obj_key", $object);
$array = Array('assoc'=>123, 345, 567);
$memcache->set("arr_key", $array);
var_dump($memcache->get('str_key'));
var_dump($memcache->get('num_key'));
var_dump($memcache->get('obj_key'));
}
else {
echo "Connection to memcached failed";
}
?>

View File

@@ -1,900 +0,0 @@
<?php
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Harun Yayli <harunyayli at gmail.com> |
+----------------------------------------------------------------------+
*/
$VERSION='$Id: memcache.php 326707 2012-07-19 19:02:42Z ab $';
define('ADMIN_USERNAME','mem'); // Admin Username
define('ADMIN_PASSWORD','1'); // Admin Password
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
$MEMCACHE_SERVERS[] = 'localhost:11211'; // add more as an array
//$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
///////////////// Password protect ////////////////////////////////////////////////////////////////
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) ||
$_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
Header("WWW-Authenticate: Basic realm=\"Memcache Login (Username: ".ADMIN_USERNAME."/Password: ".ADMIN_PASSWORD.")\"");
Header("HTTP/1.0 401 Unauthorized");
echo <<<EOB
<html><body>
<h1>Rejected!</h1>
<big>Wrong Username or Password!</big>
</body></html>
EOB;
exit;
}
///////////MEMCACHE FUNCTIONS /////////////////////////////////////////////////////////////////////
function get_host_port_from_server($server){
$values = explode(':', $server);
if (($values[0] == 'unix') && (!is_numeric( $values[1]))) {
return array($server, 0);
}
else {
return $values;
}
}
function sendMemcacheCommands($command){
global $MEMCACHE_SERVERS;
$result = array();
foreach($MEMCACHE_SERVERS as $server){
$strs = get_host_port_from_server($server);
$host = $strs[0];
$port = $strs[1];
$result[$server] = sendMemcacheCommand($host,$port,$command);
}
return $result;
}
function sendMemcacheCommand($server,$port,$command){
$s = @fsockopen($server,$port);
if (!$s){
die("Cant connect to:".$server.':'.$port);
}
fwrite($s, $command."\r\n");
$buf='';
while ((!feof($s))) {
$buf .= fgets($s, 256);
if (strpos($buf,"END\r\n")!==false){ // stat says end
break;
}
if (strpos($buf,"DELETED\r\n")!==false || strpos($buf,"NOT_FOUND\r\n")!==false){ // delete says these
break;
}
if (strpos($buf,"OK\r\n")!==false){ // flush_all says ok
break;
}
}
fclose($s);
return parseMemcacheResults($buf);
}
function parseMemcacheResults($str){
$res = array();
$lines = explode("\r\n",$str);
$cnt = count($lines);
for($i=0; $i< $cnt; $i++){
$line = $lines[$i];
$l = explode(' ',$line,3);
if (count($l)==3){
$res[$l[0]][$l[1]]=$l[2];
if ($l[0]=='VALUE'){ // next line is the value
$res[$l[0]][$l[1]] = array();
list ($flag,$size)=explode(' ',$l[2]);
$res[$l[0]][$l[1]]['stat']=array('flag'=>$flag,'size'=>$size);
$res[$l[0]][$l[1]]['value']=$lines[++$i];
}
}elseif($line=='DELETED' || $line=='NOT_FOUND' || $line=='OK'){
return $line;
}
}
return $res;
}
function dumpCacheSlab($server,$slabId,$limit){
list($host,$port) = get_host_port_from_server($server);
$resp = sendMemcacheCommand($host,$port,'stats cachedump '.$slabId.' '.$limit);
return $resp;
}
function flushServer($server){
list($host,$port) = get_host_port_from_server($server);
$resp = sendMemcacheCommand($host,$port,'flush_all');
return $resp;
}
function getCacheItems(){
$items = sendMemcacheCommands('stats items');
$serverItems = array();
$totalItems = array();
foreach ($items as $server=>$itemlist){
$serverItems[$server] = array();
$totalItems[$server]=0;
if (!isset($itemlist['STAT'])){
continue;
}
$iteminfo = $itemlist['STAT'];
foreach($iteminfo as $keyinfo=>$value){
if (preg_match('/items\:(\d+?)\:(.+?)$/',$keyinfo,$matches)){
$serverItems[$server][$matches[1]][$matches[2]] = $value;
if ($matches[2]=='number'){
$totalItems[$server] +=$value;
}
}
}
}
return array('items'=>$serverItems,'counts'=>$totalItems);
}
function getMemcacheStats($total=true){
$resp = sendMemcacheCommands('stats');
if ($total){
$res = array();
foreach($resp as $server=>$r){
foreach($r['STAT'] as $key=>$row){
if (!isset($res[$key])){
$res[$key]=null;
}
switch ($key){
case 'pid':
$res['pid'][$server]=$row;
break;
case 'uptime':
$res['uptime'][$server]=$row;
break;
case 'time':
$res['time'][$server]=$row;
break;
case 'version':
$res['version'][$server]=$row;
break;
case 'pointer_size':
$res['pointer_size'][$server]=$row;
break;
case 'rusage_user':
$res['rusage_user'][$server]=$row;
break;
case 'rusage_system':
$res['rusage_system'][$server]=$row;
break;
case 'curr_items':
$res['curr_items']+=$row;
break;
case 'total_items':
$res['total_items']+=$row;
break;
case 'bytes':
$res['bytes']+=$row;
break;
case 'curr_connections':
$res['curr_connections']+=$row;
break;
case 'total_connections':
$res['total_connections']+=$row;
break;
case 'connection_structures':
$res['connection_structures']+=$row;
break;
case 'cmd_get':
$res['cmd_get']+=$row;
break;
case 'cmd_set':
$res['cmd_set']+=$row;
break;
case 'get_hits':
$res['get_hits']+=$row;
break;
case 'get_misses':
$res['get_misses']+=$row;
break;
case 'evictions':
$res['evictions']+=$row;
break;
case 'bytes_read':
$res['bytes_read']+=$row;
break;
case 'bytes_written':
$res['bytes_written']+=$row;
break;
case 'limit_maxbytes':
$res['limit_maxbytes']+=$row;
break;
case 'threads':
$res['rusage_system'][$server]=$row;
break;
}
}
}
return $res;
}
return $resp;
}
//////////////////////////////////////////////////////
//
// don't cache this page
//
header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache"); // HTTP/1.0
function duration($ts) {
global $time;
$years = (int)((($time - $ts)/(7*86400))/52.177457);
$rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
$weeks = (int)(($rem)/(7*86400));
$days = (int)(($rem)/86400) - $weeks*7;
$hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
$mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
$str = '';
if($years==1) $str .= "$years year, ";
if($years>1) $str .= "$years years, ";
if($weeks==1) $str .= "$weeks week, ";
if($weeks>1) $str .= "$weeks weeks, ";
if($days==1) $str .= "$days day,";
if($days>1) $str .= "$days days,";
if($hours == 1) $str .= " $hours hour and";
if($hours>1) $str .= " $hours hours and";
if($mins == 1) $str .= " 1 minute";
else $str .= " $mins minutes";
return $str;
}
// create graphics
//
function graphics_avail() {
return extension_loaded('gd');
}
function bsize($s) {
foreach (array('','K','M','G') as $i => $k) {
if ($s < 1024) break;
$s/=1024;
}
return sprintf("%5.1f %sBytes",$s,$k);
}
// create menu entry
function menu_entry($ob,$title) {
global $PHP_SELF;
if ($ob==$_GET['op']){
return "<li><a class=\"child_active\" href=\"$PHP_SELF&op=$ob\">$title</a></li>";
}
return "<li><a class=\"active\" href=\"$PHP_SELF&op=$ob\">$title</a></li>";
}
function getHeader(){
$header = <<<EOB
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>MEMCACHE INFO</title>
<style type="text/css"><!--
body { background:white; font-size:100.01%; margin:0; padding:0; }
body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
* html body {font-size:0.8em}
* html p {font-size:0.8em}
* html td {font-size:0.8em}
* html th {font-size:0.8em}
* html input {font-size:0.8em}
* html submit {font-size:0.8em}
td { vertical-align:top }
a { color:black; font-weight:none; text-decoration:none; }
a:hover { text-decoration:underline; }
div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
h1.memcache { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
* html h1.memcache { margin-bottom:-7px; }
h1.memcache a:hover { text-decoration:none; color:rgb(90,90,90); }
h1.memcache span.logo {
background:rgb(119,123,180);
color:black;
border-right: solid black 1px;
border-bottom: solid black 1px;
font-style:italic;
font-size:1em;
padding-left:1.2em;
padding-right:1.2em;
text-align:right;
display:block;
width:130px;
}
h1.memcache span.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
h1.memcache span.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
h1.memcache div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
hr.memcache {
background:white;
border-bottom:solid rgb(102,102,153) 1px;
border-style:none;
border-top:solid rgb(102,102,153) 10px;
height:12px;
margin:0;
margin-top:1px;
padding:0;
}
ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
ol.menu a {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:white;
font-weight:bold;
margin-right:0em;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
margin-left: 5px;
}
ol.menu a.child_active {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:white;
font-weight:bold;
margin-right:0em;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
border-left: solid black 5px;
margin-left: 0px;
}
ol.menu span.active {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:black;
font-weight:bold;
margin-right:0em;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
border-left: solid black 5px;
}
ol.menu span.inactive {
background:rgb(193,193,244);
border:solid rgb(182,182,233) 2px;
color:white;
font-weight:bold;
margin-right:0em;
padding:0.1em 0.5em 0.1em 0.5em;
text-decoration:none;
margin-left: 5px;
}
ol.menu a:hover {
background:rgb(193,193,244);
text-decoration:none;
}
div.info {
background:rgb(204,204,204);
border:solid rgb(204,204,204) 1px;
margin-bottom:1em;
}
div.info h2 {
background:rgb(204,204,204);
color:black;
font-size:1em;
margin:0;
padding:0.1em 1em 0.1em 1em;
}
div.info table {
border:solid rgb(204,204,204) 1px;
border-spacing:0;
width:100%;
}
div.info table th {
background:rgb(204,204,204);
color:white;
margin:0;
padding:0.1em 1em 0.1em 1em;
}
div.info table th a.sortable { color:black; }
div.info table tr.tr-0 { background:rgb(238,238,238); }
div.info table tr.tr-1 { background:rgb(221,221,221); }
div.info table td { padding:0.3em 1em 0.3em 1em; }
div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
div.info table td h3 {
color:black;
font-size:1.1em;
margin-left:-0.3em;
}
.td-0 a , .td-n a, .tr-0 a , tr-1 a {
text-decoration:underline;
}
div.graph { margin-bottom:1em }
div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
div.graph table td.td-0 { background:rgb(238,238,238); }
div.graph table td.td-1 { background:rgb(221,221,221); }
div.graph table td { padding:0.2em 1em 0.4em 1em; }
div.div1,div.div2 { margin-bottom:1em; width:35em; }
div.div3 { position:absolute; left:40em; top:1em; width:580px; }
//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
div.sorting { margin:1.5em 0em 1.5em 2em }
.center { text-align:center }
.aright { position:absolute;right:1em }
.right { text-align:right }
.ok { color:rgb(0,200,0); font-weight:bold}
.failed { color:rgb(200,0,0); font-weight:bold}
span.box {
border: black solid 1px;
border-right:solid black 2px;
border-bottom:solid black 2px;
padding:0 0.5em 0 0.5em;
margin-right:1em;
}
span.green { background:#60F060; padding:0 0.5em 0 0.5em}
span.red { background:#D06030; padding:0 0.5em 0 0.5em }
div.authneeded {
background:rgb(238,238,238);
border:solid rgb(204,204,204) 1px;
color:rgb(200,0,0);
font-size:1.2em;
font-weight:bold;
padding:2em;
text-align:center;
}
input {
background:rgb(153,153,204);
border:solid rgb(102,102,153) 2px;
color:white;
font-weight:bold;
margin-right:1em;
padding:0.1em 0.5em 0.1em 0.5em;
}
//-->
</style>
</head>
<body>
<div class="head">
<h1 class="memcache">
<span class="logo"><a href="http://pecl.php.net/package/memcache">memcache</a></span>
<span class="nameinfo">memcache.php by <a href="http://livebookmark.net">Harun Yayli</a></span>
</h1>
<hr class="memcache">
</div>
<div class=content>
EOB;
return $header;
}
function getFooter(){
global $VERSION;
$footer = '</div><!-- Based on apc.php '.$VERSION.'--></body>
</html>
';
return $footer;
}
function getMenu(){
global $PHP_SELF;
echo "<ol class=menu>";
if ($_GET['op']!=4){
echo <<<EOB
<li><a href="$PHP_SELF&op={$_GET['op']}">Refresh Data</a></li>
EOB;
}
else {
echo <<<EOB
<li><a href="$PHP_SELF&op=2}">Back</a></li>
EOB;
}
echo
menu_entry(1,'View Host Stats'),
menu_entry(2,'Variables');
echo <<<EOB
</ol>
<br/>
EOB;
}
// TODO, AUTH
$_GET['op'] = !isset($_GET['op'])? '1':$_GET['op'];
$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : '';
$PHP_SELF=$PHP_SELF.'?';
$time = time();
// sanitize _GET
foreach($_GET as $key=>$g){
$_GET[$key]=htmlentities($g);
}
// singleout
// when singleout is set, it only gives details for that server.
if (isset($_GET['singleout']) && $_GET['singleout']>=0 && $_GET['singleout'] <count($MEMCACHE_SERVERS)){
$MEMCACHE_SERVERS = array($MEMCACHE_SERVERS[$_GET['singleout']]);
}
// display images
if (isset($_GET['IMG'])){
$memcacheStats = getMemcacheStats();
$memcacheStatsSingle = getMemcacheStats(false);
if (!graphics_avail()) {
exit(0);
}
function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
global $col_black;
$x1=$x+$w-1;
$y1=$y+$h-1;
imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
imagerectangle($im, $x, $y1, $x1, $y, $color1);
if ($text) {
if ($placeindex>0) {
if ($placeindex<16)
{
$px=5;
$py=$placeindex*12+6;
imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
imagestring($im,2,$px,$py-6,$text,$color1);
} else {
if ($placeindex<31) {
$px=$x+40*2;
$py=($placeindex-15)*12+6;
} else {
$px=$x+40*2+100*intval(($placeindex-15)/15);
$py=($placeindex%15)*12+6;
}
imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
imagestring($im,2,$px+2,$py-6,$text,$color1);
}
} else {
imagestring($im,4,$x+5,$y1-16,$text,$color1);
}
}
}
function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
$r=$diameter/2;
$w=deg2rad((360+$start+($end-$start)/2)%360);
if (function_exists("imagefilledarc")) {
// exists only if GD 2.0.1 is avaliable
imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
} else {
imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
}
if ($text) {
if ($placeindex>0) {
imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
} else {
imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
}
}
}
$size = GRAPH_SIZE; // image size
$image = imagecreate($size+50, $size+10);
$col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
$col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
$col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
$col_black = imagecolorallocate($image, 0, 0, 0);
imagecolortransparent($image,$col_white);
switch ($_GET['IMG']){
case 1: // pie chart
$tsize=$memcacheStats['limit_maxbytes'];
$avail=$tsize-$memcacheStats['bytes'];
$x=$y=$size/2;
$angle_from = 0;
$fuzz = 0.000001;
foreach($memcacheStatsSingle as $serv=>$mcs) {
$free = $mcs['STAT']['limit_maxbytes']-$mcs['STAT']['bytes'];
$used = $mcs['STAT']['bytes'];
if ($free>0){
// draw free
$angle_to = ($free*360)/$tsize;
$perc =sprintf("%.2f%%", ($free *100) / $tsize) ;
fill_arc($image,$x,$y,$size,$angle_from,$angle_from + $angle_to ,$col_black,$col_green,$perc);
$angle_from = $angle_from + $angle_to ;
}
if ($used>0){
// draw used
$angle_to = ($used*360)/$tsize;
$perc =sprintf("%.2f%%", ($used *100) / $tsize) ;
fill_arc($image,$x,$y,$size,$angle_from,$angle_from + $angle_to ,$col_black,$col_red, '('.$perc.')' );
$angle_from = $angle_from+ $angle_to ;
}
}
break;
case 2: // hit miss
$hits = ($memcacheStats['get_hits']==0) ? 1:$memcacheStats['get_hits'];
$misses = ($memcacheStats['get_misses']==0) ? 1:$memcacheStats['get_misses'];
$total = $hits + $misses ;
fill_box($image, 30,$size,50,-$hits*($size-21)/$total,$col_black,$col_green,sprintf("%.1f%%",$hits*100/$total));
fill_box($image,130,$size,50,-max(4,($total-$hits)*($size-21)/$total),$col_black,$col_red,sprintf("%.1f%%",$misses*100/$total));
break;
}
header("Content-type: image/png");
imagepng($image);
exit;
}
echo getHeader();
echo getMenu();
switch ($_GET['op']) {
case 1: // host stats
$phpversion = phpversion();
$memcacheStats = getMemcacheStats();
$memcacheStatsSingle = getMemcacheStats(false);
$mem_size = $memcacheStats['limit_maxbytes'];
$mem_used = $memcacheStats['bytes'];
$mem_avail= $mem_size-$mem_used;
$startTime = time()-array_sum($memcacheStats['uptime']);
$curr_items = $memcacheStats['curr_items'];
$total_items = $memcacheStats['total_items'];
$hits = ($memcacheStats['get_hits']==0) ? 1:$memcacheStats['get_hits'];
$misses = ($memcacheStats['get_misses']==0) ? 1:$memcacheStats['get_misses'];
$sets = $memcacheStats['cmd_set'];
$req_rate = sprintf("%.2f",($hits+$misses)/($time-$startTime));
$hit_rate = sprintf("%.2f",($hits)/($time-$startTime));
$miss_rate = sprintf("%.2f",($misses)/($time-$startTime));
$set_rate = sprintf("%.2f",($sets)/($time-$startTime));
echo <<< EOB
<div class="info div1"><h2>General Cache Information</h2>
<table cellspacing=0><tbody>
<tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
EOB;
echo "<tr class=tr-0><td class=td-0>Memcached Host". ((count($MEMCACHE_SERVERS)>1) ? 's':'')."</td><td>";
$i=0;
if (!isset($_GET['singleout']) && count($MEMCACHE_SERVERS)>1){
foreach($MEMCACHE_SERVERS as $server){
echo ($i+1).'. <a href="'.$PHP_SELF.'&singleout='.$i++.'">'.$server.'</a><br/>';
}
}
else{
echo '1.'.$MEMCACHE_SERVERS[0];
}
if (isset($_GET['singleout'])){
echo '<a href="'.$PHP_SELF.'">(all servers)</a><br/>';
}
echo "</td></tr>\n";
echo "<tr class=tr-1><td class=td-0>Total Memcache Cache</td><td>".bsize($memcacheStats['limit_maxbytes'])."</td></tr>\n";
echo <<<EOB
</tbody></table>
</div>
<div class="info div1"><h2>Memcache Server Information</h2>
EOB;
foreach($MEMCACHE_SERVERS as $server){
echo '<table cellspacing=0><tbody>';
echo '<tr class=tr-1><td class=td-1>'.$server.'</td><td><a href="'.$PHP_SELF.'&server='.array_search($server,$MEMCACHE_SERVERS).'&op=6">[<b>Flush this server</b>]</a></td></tr>';
echo '<tr class=tr-0><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),'</td></tr>';
echo '<tr class=tr-1><td class=td-0>Uptime</td><td>',duration($memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),'</td></tr>';
echo '<tr class=tr-0><td class=td-0>Memcached Server Version</td><td>'.$memcacheStatsSingle[$server]['STAT']['version'].'</td></tr>';
echo '<tr class=tr-1><td class=td-0>Used Cache Size</td><td>',bsize($memcacheStatsSingle[$server]['STAT']['bytes']),'</td></tr>';
echo '<tr class=tr-0><td class=td-0>Total Cache Size</td><td>',bsize($memcacheStatsSingle[$server]['STAT']['limit_maxbytes']),'</td></tr>';
echo '</tbody></table>';
}
echo <<<EOB
</div>
<div class="graph div3"><h2>Host Status Diagrams</h2>
<table cellspacing=0><tbody>
EOB;
$size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
echo <<<EOB
<tr>
<td class=td-0>Cache Usage</td>
<td class=td-1>Hits &amp; Misses</td>
</tr>
EOB;
echo
graphics_avail() ?
'<tr>'.
"<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF&IMG=1&".(isset($_GET['singleout'])? 'singleout='.$_GET['singleout'].'&':'')."$time\"></td>".
"<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF&IMG=2&".(isset($_GET['singleout'])? 'singleout='.$_GET['singleout'].'&':'')."$time\"></td></tr>\n"
: "",
'<tr>',
'<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
'<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$hits.sprintf(" (%.1f%%)",$hits*100/($hits+$misses)),"</td>\n",
'</tr>',
'<tr>',
'<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
'<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$misses.sprintf(" (%.1f%%)",$misses*100/($hits+$misses)),"</td>\n";
echo <<< EOB
</tr>
</tbody></table>
<br/>
<div class="info"><h2>Cache Information</h2>
<table cellspacing=0><tbody>
<tr class=tr-0><td class=td-0>Current Items(total)</td><td>$curr_items ($total_items)</td></tr>
<tr class=tr-1><td class=td-0>Hits</td><td>{$hits}</td></tr>
<tr class=tr-0><td class=td-0>Misses</td><td>{$misses}</td></tr>
<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
<tr class=tr-0><td class=td-0>Set Rate</td><td>$set_rate cache requests/second</td></tr>
</tbody></table>
</div>
EOB;
break;
case 2: // variables
$m=0;
$cacheItems= getCacheItems();
$items = $cacheItems['items'];
$totals = $cacheItems['counts'];
$maxDump = MAX_ITEM_DUMP;
foreach($items as $server => $entries) {
echo <<< EOB
<div class="info"><table cellspacing=0><tbody>
<tr><th colspan="2">$server</th></tr>
<tr><th>Slab Id</th><th>Info</th></tr>
EOB;
foreach($entries as $slabId => $slab) {
$dumpUrl = $PHP_SELF.'&op=2&server='.(array_search($server,$MEMCACHE_SERVERS)).'&dumpslab='.$slabId;
echo
"<tr class=tr-$m>",
"<td class=td-0><center>",'<a href="',$dumpUrl,'">',$slabId,'</a>',"</center></td>",
"<td class=td-last><b>Item count:</b> ",$slab['number'],'<br/><b>Age:</b>',duration($time-$slab['age']),'<br/> <b>Evicted:</b>',((isset($slab['evicted']) && $slab['evicted']==1)? 'Yes':'No');
if ((isset($_GET['dumpslab']) && $_GET['dumpslab']==$slabId) && (isset($_GET['server']) && $_GET['server']==array_search($server,$MEMCACHE_SERVERS))){
echo "<br/><b>Items: item</b><br/>";
$items = dumpCacheSlab($server,$slabId,$slab['number']);
// maybe someone likes to do a pagination here :)
$i=1;
foreach($items['ITEM'] as $itemKey=>$itemInfo){
$itemInfo = trim($itemInfo,'[ ]');
echo '<a href="',$PHP_SELF,'&op=4&server=',(array_search($server,$MEMCACHE_SERVERS)),'&key=',base64_encode($itemKey).'">',$itemKey,'</a>';
if ($i++ % 10 == 0) {
echo '<br/>';
}
elseif ($i!=$slab['number']+1){
echo ',';
}
}
}
echo "</td></tr>";
$m=1-$m;
}
echo <<<EOB
</tbody></table>
</div><hr/>
EOB;
}
break;
break;
case 4: //item dump
if (!isset($_GET['key']) || !isset($_GET['server'])){
echo "No key set!";
break;
}
// I'm not doing anything to check the validity of the key string.
// probably an exploit can be written to delete all the files in key=base64_encode("\n\r delete all").
// somebody has to do a fix to this.
$theKey = htmlentities(base64_decode($_GET['key']));
$theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
list($h,$p) = get_host_port_from_server($theserver);
$r = sendMemcacheCommand($h,$p,'get '.$theKey);
echo <<<EOB
<div class="info"><table cellspacing=0><tbody>
<tr><th>Server<th>Key</th><th>Value</th><th>Delete</th></tr>
EOB;
if (!isset($r['VALUE'])) {
echo "<tr><td class=td-0>",$theserver,"</td><td class=td-0>",$theKey,
"</td><td>[The requested item was not found or has expired]</td>",
"<td></td>","</tr>";
}
else {
echo "<tr><td class=td-0>",$theserver,"</td><td class=td-0>",$theKey,
" <br/>flag:",$r['VALUE'][$theKey]['stat']['flag'],
" <br/>Size:",bsize($r['VALUE'][$theKey]['stat']['size']),
"</td><td>",chunk_split($r['VALUE'][$theKey]['value'],40),"</td>",
'<td><a href="',$PHP_SELF,'&op=5&server=',(int)$_GET['server'],'&key=',base64_encode($theKey),"\">Delete</a></td>","</tr>";
}
echo <<<EOB
</tbody></table>
</div><hr/>
EOB;
break;
case 5: // item delete
if (!isset($_GET['key']) || !isset($_GET['server'])){
echo "No key set!";
break;
}
$theKey = htmlentities(base64_decode($_GET['key']));
$theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
list($h,$p) = get_host_port_from_server($theserver);
$r = sendMemcacheCommand($h,$p,'delete '.$theKey);
echo 'Deleting '.$theKey.':'.$r;
break;
case 6: // flush server
$_GET['server'] = empty($_GET['server']) ? 0 : $_GET['server'];
$theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
$r = flushServer($theserver);
echo 'Flush '.$theserver.":".$r;
break;
}
echo getFooter();
?>

Binary file not shown.

Binary file not shown.

View File

@@ -1,12 +1,17 @@
# PHP # PHP
# https://windows.php.net/download/ # https://windows.php.net/download/
# NTS = Non Thread Safe # NTS = Non Thread Safe
*PHP-8.4=https://windows.php.net/downloads/releases/php-8.4.2-nts-Win32-vs17-x64.zip *PHP-8.4=https://windows.php.net/downloads/releases/archives/php-8.4.2-nts-Win32-vs17-x64.zip
*PHP-8.3=https://windows.php.net/downloads/releases/php-8.3.15-nts-Win32-vs16-x64.zip *PHP-8.3=https://windows.php.net/downloads/releases/archives/php-8.3.15-nts-Win32-vs16-x64.zip
*PHP-8.2=https://windows.php.net/downloads/releases/php-8.2.27-nts-Win32-vs16-x64.zip *PHP-8.2=https://windows.php.net/downloads/releases/archives/php-8.2.27-nts-Win32-vs16-x64.zip
*PHP-8.1=https://windows.php.net/downloads/releases/php-8.1.31-nts-Win32-vs16-x64.zip *PHP-8.1=https://windows.php.net/downloads/releases/archives/php-8.1.31-nts-Win32-vs16-x64.zip
---
# Web Servers
Apache-2.4.63=https://www.apachelounge.com/download/VS17/binaries/httpd-2.4.63-250122-win64-VS17.zip
Nginx-1.27.3=https://nginx.org/download/nginx-1.27.3.zip
--- ---

View File

@@ -2,5 +2,32 @@
AutoCreateDatabase=true AutoCreateDatabase=true
Cached=true Cached=true
# Blank: an empty project
Blank=
# WordPress # WordPress
WordPress=https://wordpress.org/latest.zip WordPress=https://wordpress.org/latest.tar.gz
------------------------------------------------------
# Laravel
Laravel=composer create-project laravel/laravel %s --prefer-dist
Laravel CLI=laravel new %s
# Laravel (zip)=PATH-TO-YOUR-ZIP
------------------------------------------------------
# CakePHP
### CakePHP=composer create-project --prefer-dist cakephp/app %s
# Symfony
Symfony=composer create-project symfony/website-skeleton %s

View File

@@ -1,167 +1,106 @@
<?php <?php
if (!empty($_GET['q'])) { if (!empty($_GET['q'])) {
switch ($_GET['q']) { $query = htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8');
case 'info':
phpinfo(); switch ($query) {
exit; case 'info':
break; phpinfo();
} exit;
default:
header("HTTP/1.0 404 Not Found");
echo "Invalid query parameter.";
exit;
}
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Laragon</title> <title>Laragon</title>
<link href="https://fonts.googleapis.com/css?family=Karla:400" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Karla:400" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="https://i.imgur.com/ky9oqct.png" type="image/png"> <style>
<style> html, body {
*, height: 100%;
:before *, margin: 0;
:after * { padding: 0;
box-sizing: border-box; font-family: 'Karla', sans-serif;
} font-weight: 100;
background-color: #f9f9f9;
color: #333;
}
body { .container {
margin: 0; display: flex;
min-height: 100vh; justify-content: center;
font-weight: 100; align-items: center;
font-family: 'Karla', sans-serif; height: 100%;
font-size: 18px; text-align: center;
} }
header, .content {
main, max-width: 800px;
nav, padding: 100px;
aside { background: #fff;
padding: 1rem; border-radius: 8px;
margin: auto; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 1200px; }
text-align: center;
}
header { .title {
display: flex; font-size: 60px;
flex-wrap: wrap; margin: 0;
justify-content: center;
align-items: center; }
}
.header__item { .info {
margin: 0; margin-top: 20px;
padding: 1rem; font-size: 18px;
} line-height: 1.6;
}
.header--logo { .info a {
height: 8rem; color: #007bff;
} text-decoration: none;
}
h1 { .info a:hover {
font-size: 5rem; color: #0056b3;
} text-decoration: underline;
}
main { .opt {
background-color: #f5f5f5; margin-top: 30px;
} }
nav { .opt a {
width: 100%; font-size: 18px;
} color: #007bff;
text-decoration: none;
}
ul { .opt a:hover {
list-style: none; color: #0056b3;
padding: 0; text-decoration: underline;
margin: auto; }
} </style>
a {
color: #37ADFF;
font-weight: 900;
text-decoration: none;
}
a:hover {
color: red;
font-weight: 900;
transition: 300ms;
}
main a {
color: grey;
}
nav a {
display: block;
margin: 1rem 0;
}
nav a:after {
content: '→';
margin-left: 0.5rem;
}
.alert {
color: red;
font-weight: 900;
}
@media (min-width: 650px) {
h1 {
font-size: 10rem;
}
}
</style>
</head> </head>
<body> <body>
<header> <div class="container">
<img class="header__item header--logo" src="https://i.imgur.com/ky9oqct.png" alt="Offline"> <div class="content">
<h1 class="header__item header--title" title="Laragon">Laragon</h1> <h1 class="title" title="Laragon">Laragon</h1>
</header> <div class="info">
<main> <p><?php echo htmlspecialchars($_SERVER['SERVER_SOFTWARE'], ENT_QUOTES, 'UTF-8'); ?></p>
<p> <p>PHP version: <?php echo htmlspecialchars(phpversion(), ENT_QUOTES, 'UTF-8'); ?>
<?php print($_SERVER['SERVER_SOFTWARE']); ?> <a title="phpinfo()" href="/?q=info">info</a>
</p> </p>
<p> <p>Document Root: <?php echo htmlspecialchars($_SERVER['DOCUMENT_ROOT'], ENT_QUOTES, 'UTF-8'); ?></p>
PHP version: <?php print PHP_VERSION; ?> <span><a title="phpinfo()" href="/?q=info">info</a></span> </div>
</p> <div class="opt">
<p> <p><a title="Getting Started" href="https://laragon.org/docs">Getting Started</a></p>
Document Root: <?php print($_SERVER['DOCUMENT_ROOT']); ?> </div>
</p> </div>
<p> </div>
<a title="Getting Started" href="https://laragon.org/docs">Getting Started</a>
</p>
</main>
<?php
$dirList = glob('*', GLOB_ONLYDIR);
if (!empty($dirList)) :
?>
<nav>
<ul>
<?php
foreach ($dirList as $key => $value) :
$link = 'https://' . $value . '.test';
?>
<a href="<?php echo $link; ?>" target="_blank"><?php echo $link; ?></a>
<?php
endforeach;
?>
</ul>
</nav>
<?php
else :
?>
<aside>
<p class="alert">There are no directories, create your first project now</p>
<div>
<img src="https://i.imgur.com/3Sgu8XI.png" alt="Offline">
</div>
</aside>
<?php
endif;
?>
</body> </body>
</html> </html>