1 Commits

Author SHA1 Message Date
Leo Khoa
ad5cbead0e Update README.md
Focus on PHP, Node.js, Python
2025-01-09 13:22:36 +01:00
72 changed files with 7143 additions and 984 deletions

View File

@@ -1,223 +0,0 @@
# Laragon - Windows Development Environment
Laragon is a portable, isolated Windows development environment for PHP, Node.js, and Python. This repository contains the distribution files and configuration templates for Laragon.
Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
## Critical Limitations
**WINDOWS-ONLY ENVIRONMENT**: Laragon is exclusively a Windows GUI application. The main executable (laragon.exe) is a Windows PE32+ binary that cannot run on Linux or macOS. Development and testing of the actual Laragon environment requires Windows.
**NO BUILD PROCESS**: This repository contains pre-built binaries and configuration files. There is no source code compilation, build system, or CI/CD pipeline.
**NO AUTOMATED TESTS**: This is a packaged application distribution, not a development project with test suites.
## Working Effectively on Linux/macOS
While you cannot run Laragon itself, you can:
### Repository Structure Exploration
- View and understand the file structure: `ls -la /path/to/laragon`
- Examine configuration files: `find . -name "*.ini" -o -name "*.conf"`
- Check included software versions: `grep -r "Version=" usr/laragon.ini`
- List bundled tools: `ls -la bin/`
### Configuration Management
- View main configuration: `cat usr/laragon.ini`
- Check site templates: `cat usr/sites.conf`
- Examine Procfile format: `cat usr/Procfile`
- Review user customization: `cat usr/user.cmd`
### Documentation Tasks
- Edit README.md and documentation files
- Update configuration templates
- Modify default project templates in www/
- Update site configuration examples
## Laragon Architecture
### Core Components
- **laragon.exe**: Main Windows GUI application (5.3MB PE32+ executable)
- **bin/**: Bundled software packages
- PHP (current versions with auto-update support)
- MySQL (current versions with auto-update support)
- Nginx (current versions)
- Apache (configurable)
- Composer (PHP dependency manager)
- HeidiSQL (database management GUI)
- Cmder (terminal emulator)
- Notepad++ (text editor)
- Sendmail (mail handling)
**Note**: This repository contains historical/example versions (PHP 5.4.9, MySQL 5.1.72, Nginx 1.14.0) but actual Laragon releases bundle current software versions with an integrated auto-update system for minor version updates.
### Configuration Files
- **usr/laragon.ini**: Main configuration (service versions, preferences)
- **usr/sites.conf**: Project template definitions
- **usr/Procfile**: Custom service definitions
- **usr/user.cmd**: User startup customizations
- **etc/**: Service-specific configurations (Apache, Nginx, PHP)
### Directory Structure
```
laragon/
├── laragon.exe # Main Windows GUI application
├── bin/ # Bundled software (PHP, MySQL, Nginx, etc.)
├── etc/ # Configuration files for services
├── usr/ # User configurations and templates
├── www/ # Default web root directory
├── README.md # Project documentation
├── CHANGELOG.md # Version history
└── SECURITY.md # Security policy
```
## Key Features
- **Portable**: Entire environment can be moved between Windows machines
- **Auto-configuration**: Services are automatically configured when started
- **Auto-update system**: Integrated minor version updates for bundled software
- **Current software versions**: Ships with up-to-date PHP, MySQL, Apache, and other tools
- **Pretty URLs**: Uses `.test` domains instead of localhost
- **Multi-version support**: Can switch between different PHP/MySQL versions
- **Project templates**: Built-in templates for WordPress, Laravel, Symfony
## Common Tasks
### Examining Service Versions
```bash
# Check configured versions (note: repository contains historical versions)
grep "Version=" usr/laragon.ini
# List available software in bin directory (historical snapshot)
ls bin/
```
**Important**: The versions shown in this repository (PHP 5.4.9, MySQL 5.1.72, etc.) are historical examples. Actual Laragon installations include current software versions with automatic update capabilities.
### Configuration File Management
```bash
# View main configuration
cat usr/laragon.ini
# Check site template definitions
cat usr/sites.conf
# Examine user customization file
cat usr/user.cmd
```
### Project Template Analysis
```bash
# Check available project types
grep "^[A-Za-z]" usr/sites.conf | grep "="
# View default web page
cat www/index.php
```
### Structure Exploration
```bash
# Repository root contents
ls -la
# Find all configuration files
find . -name "*.ini" -o -name "*.conf" | head -10
# Check documentation files
find . -name "*.md"
```
## Validation on Windows
**Note**: These steps can only be performed on a Windows machine with Laragon installed:
### Basic Functionality Testing
1. Start Laragon GUI application
2. Verify all services start (Apache/Nginx, MySQL, PHP)
3. Access http://localhost to see default page
4. Create a test project using quick app creation
5. Verify pretty URLs work (e.g., http://testapp.test)
### Configuration Validation
1. Modify usr/laragon.ini settings
2. Restart Laragon to apply changes
3. Verify service versions match configuration
4. Test custom Procfile entries
5. Validate user.cmd customizations
## File Editing Guidelines
### Safe to Edit
- **Documentation**: README.md, CHANGELOG.md, SECURITY.md
- **Configuration templates**: usr/laragon.ini, usr/sites.conf
- **Default web content**: www/index.php
- **User scripts**: usr/user.cmd, usr/Procfile
### Do Not Modify
- **Binary files**: laragon.exe, all files in bin/
- **Service configurations**: etc/ files (unless creating templates)
- **Git ignored items**: See .gitignore for excluded files
## Development Workflow
### For Configuration Changes
1. Edit configuration files using text editors
2. Validate syntax if applicable (e.g., INI format for laragon.ini)
3. Test changes on Windows Laragon installation
4. Document changes in comments or README
### For Documentation Updates
1. Edit Markdown files directly
2. Ensure proper formatting and links
3. Validate Markdown syntax
4. No special testing required
## Repository Maintenance
### Adding New Project Templates
1. Edit usr/sites.conf
2. Follow existing format: `ProjectName=installation_command`
3. Test template on Windows Laragon installation
4. Document new template in README if needed
### Configuration Updates
1. Modify relevant .ini or .conf files
2. Ensure Windows compatibility
3. Test with actual Laragon installation
4. Update documentation if behavior changes
## Common File Locations
### Frequently Referenced Files
```bash
# Main configuration
usr/laragon.ini
# Project templates
usr/sites.conf
# Default web page
www/index.php
# User customization
usr/user.cmd
# Main documentation
README.md
```
### Configuration Paths
```bash
# Apache configuration
etc/apache2/
# Nginx configuration
etc/nginx/
# PHP configuration
etc/php/
# SSL certificates
etc/ssl/
```
This repository serves as the distribution package for Laragon. All development and testing of the actual development environment functionality must be done on Windows machines with Laragon installed.

View File

@@ -1 +0,0 @@
https://github.com/leokhoa/laragon/releases

View File

@@ -6,20 +6,18 @@ Laragon is a portable, isolated, fast & powerful universal development environme
Laragon is great for building and managing modern web applications. It is focused on performance - designed around stability, simplicity, flexibility and freedom. Laragon is great for building and managing modern web applications. It is focused on performance - designed around stability, simplicity, flexibility and freedom.
Laragon is very lightweight and will stay as lean as possible. The core binary itself is less than 6MB and uses around 4MB - 10MB RAM when running. Laragon is very lightweight and will stay as lean as possible. The core binary itself is less than 2MB and uses less than 4MB RAM when running.
Laragon doesn't use Windows services. It has its own `service orchestration` which manages services asynchronously and non-blocking so you'll find things run fast & smoothly with Laragon. Laragon doesn't use Windows services. It has its own `service orchestration` which manages services asynchronously and non-blocking so you'll find things run fast & smoothly with Laragon.
Enjoy! Enjoy!
> Starting with Laragon 7.x, a license is required to use Laragon. For more details, visit <https://laragon.lemonsqueezy.com/>.
## Features ## Features
- **Pretty URLs** - **Pretty URLs**
Use `app.test` instead of `localhost/app`. Use `app.test` instead of `localhost/app`.
- **Portable** - **Portable**
You can move Laragon folder around (to another disks, to another laptops, sync to Cloud,...) without any worries. You can move Laragon folder around (to another disks, to another laptops, sync to Cloud,...) without any worries.
- **Isolated** - **Isolated**
Laragon has an isolated environment with your OS - it will keep your system clean. Laragon has an isolated environment with your OS - it will keep your system clean.
- **Easy Operation** - **Easy Operation**
@@ -28,7 +26,7 @@ Enjoy!
Laragon comes with a modern architecture which is suitable to build modern web apps. You can work with both Apache & Nginx as they are fully-managed. Laragon comes with a modern architecture which is suitable to build modern web apps. You can work with both Apache & Nginx as they are fully-managed.
Also, Laragon makes things a lot easier: Also, Laragon makes things a lot easier:
- Wanna have a Wordpress CMS? Just 1 click. - Wanna have a Wordpress CMS? Just 1 click.
- Wanna show your local project to customers? Just 1 click. - Wanna show your local project to customers? Just 1 click.
- Wanna enable/disable a PHP extension? Just 1 click. - Wanna enable/disable a PHP extension? Just 1 click.
@@ -39,7 +37,7 @@ Enjoy!
## How fast? ## How fast?
Laragon starts instantly. You can set Laragon autorun when Windows starts. When running, Laragon uses just a little amount of your RAM. Laragon starts instantly. You can set Laragon autorun when Windows starts. When running, Laragon uses just a little amount of your RAM.
Here is the GUI of Laragon: Here is the GUI of Laragon:
![0_1513173700919_01-dashboard.png](https://i.imgur.com/0py3k1X.png) ![0_1513173700919_01-dashboard.png](https://i.imgur.com/0py3k1X.png)
## How easy? ## How easy?
- Laragon is very easy to install & upgrade. Just download the latest version and click `Next, Next, Next...` - Laragon is very easy to install & upgrade. Just download the latest version and click `Next, Next, Next...`

View File

@@ -1,13 +0,0 @@
# 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 = سيحصل تطبيقك على رابط لطيف ---> https://app.test 901 = سيحصل تطبيقك على رابط لطيف ---> http://app.test
902 = أضف محرر النص و موجه الأوامر إلى قائمة النقر بزر الفأرة الأيمن 902 = أضف محرر النص و موجه الأوامر إلى قائمة النقر بزر الفأرة الأيمن
903 = طرق سريعة لفتح محرر النصوص وموجه الاوامر 903 = طرق سريعة لفتح محرر النصوص وموجه الاوامر
904 = عرض ملف اقرئني 904 = عرض ملف اقرئني
905 = تشغيل لاراقون 905 = تشغيل لاراقون
# SSL # SSL
906 = Auto-generated SSL Certificates 906 = إنشاء تلقائي لشهادات SSL
# 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 ---> https://app.test 901 = Sizin tətbiqiniz qısa yol əldə edəcək ---> http://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 = Твоето приложение ще изполва "красиви" линкове ---> https://app.test 901 = Твоето приложение ще изполва "красиви" линкове ---> http://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=你的“项目”将得到优雅链接 ---> https://项目.test 901=你的“项目”将得到优雅链接 ---> http://项目.test
902=添加 Sublime Text 和 Terminal 到右击菜单 902=添加 Sublime Text 和 Terminal 到右击菜单
903=快速打开 文本编辑器 和 命令行 903=快速打开 文本编辑器 和 命令行
904=查看README文件 904=查看README文件

View File

@@ -1,257 +1,292 @@
-------------------------------------------------------- --------------------------------------------------------
author: Kyomini - Kyomini@qq.com - https://laragon.com.cn author: SiderealArt - admin at siderealart.me - https://siderealart.me/
date: 20160802 date: 20220125
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=好的 118=OK
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=Windows系統啟動時運行Laragon 310=讓 Laragon 隨 Windows 啟動
311=Windows系統啟動時自動運行Laragon 311=讓 Laragon 隨 Windows 自動啟動
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 > 郵件接收 331=此功能將幫助快速瀏覽郵件內容\n也可以透過:\n單 > PHP > MailCatcher 來檢視最新郵件的內容
340=Gmail 地址 340=Gmail 帳號
341=Gmail 密碼 341=Gmail 密碼
342=測試送郵件 342=測試送郵件
343=妳看到的Gmail密碼將被加密\n啟用後,可以通過互聯網輕松發送郵件,只需壹行: 343=您可能需要在您的 Google 帳號中允許 「低安全性應用程式存取」。\n您的 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 將調用NodeJs來為妳創建虛擬主機! 406=偵測到新專案\nLaragon 將呼叫 Node.js 來幫您建立虛擬主機!
# 提示 # 提示
500=線幫助 500=線幫助
501=左鍵單擊: Laragon - 右鍵單擊: 菜 501=左鍵點擊:Laragon - 右鍵點擊:選
502=開始頁面 502=開始頁面
503=數據庫管理 503=資料庫管理
504=打開命令提示 (快捷鍵: CTRL+ALT+T) 504=打開命令提示字元 (快捷鍵: CTRL+ALT+T)
505=Laragon將會調用Nodejs來創建虛擬主機 \n如果妳想要這個功能無需調用Nodejs \n作為Administrator運行Laragon 505=Laragon 將會呼叫 Node.js 來建立虛擬主機\n若您不想要使用 Node.js\n請以管理員身分執行 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=哦NoLaragon檢測到異常 716=哦Laragon 偵測到例外狀況
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服務在 services in 菜單 > 參數 > 服務 & 端口 725=必須在選單 > 設定 > 服務 & 連接埠中啟用 Apache MySQL 服務!
# 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=作為管理員手動編輯hosts文件 223=點擊以手動以管理員身分編輯 host 檔案
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 && Terminal 831=加入 Sublime Text && 終端機
832=移除 Sublime Text && Terminal 832=移除 Sublime Text && 終端機
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=妳的“項目”將得到優雅鏈接 ---> https://項目.test 901=美化您的應用程式的網址 ---> http://app.test
902=添加 Sublime Text 和 Terminal 到右擊菜 902= Sublime Text 和 終端機加入右鍵選
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 - https://codepoint.dk author: Claus Munch - claus@codepoint.dk - http://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 ---> https://app.test 901 = Je app zal een mooie url krijgen ---> http://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: 7.0.1 version: 3.5
author: leokhoa - leokhoa at gmail.com - https://laragon.org author: leokhoa - leokhoa at gmail.com - https://laragon.org
date: 20250124 date: 20181016
-------------------------------------------------------- --------------------------------------------------------
# Main Interface # Main Interface
100 = Start All 100 = Start All
@@ -111,7 +111,7 @@ date: 20250124
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 Terminal (Cmder) 504 = Open Command Prompt (Hotkey: CTRL+ALT+T)
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: 20250124
# 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 ---> https://app.test 901 = Your app will get a pretty url ---> http://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,10 +290,3 @@ date: 20250124
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 ---> https://app.test 901=Votre application aura une jolie URL ---> http://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 ---> https://app.test 901=Ihre Anwendung bekommt diese URL ---> http://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 ---> https://app.test 901=Η εφαρμογή σου θα αποκτήσει pretty url ---> http://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 ---> https://app.test a https://localhost/app helyett 901 = Alkalmazása szép url-t kap ---> http://app.test a http://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 ---> https://app.test dari pada https://localhost/app 901 = Aplikasi Anda akan mendapatkan url yang cantik ---> http://app.test dari pada http://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 ---> https://app.test 901=La tua app avrà una pretty url ---> http://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になりますよ ---> https://app.test 901 = あなたのアプリはとても愛らしいURLになりますよ ---> http://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 = 당신의 앱은 https://localhost/app 대신에 예쁜 url을 얻을 것입니다 ---> https://app.test 901 = 당신의 앱은 http://localhost/app 대신에 예쁜 url을 얻을 것입니다 ---> http://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 ---> https://app.test 901 = Apl anda akan mendapat url cantik ---> http://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 ---> https://app.test 901=Appen din vil få normal url ---> http://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

@@ -1,8 +1,8 @@
-------------------------------------------------------- --------------------------------------------------------
version: 3.5 --------------------------------------------------------
version: 2.0.5
author: Milad GanjAli - miladstory@gmail.com author: Milad GanjAli - miladstory@gmail.com
author: Keramat Jokar - keramatjokar8855@gmail.com date: 20161121
date: 20250111
-------------------------------------------------------- --------------------------------------------------------
# Main Interface # Main Interface
100 = همه را شروع کن 100 = همه را شروع کن
@@ -36,6 +36,7 @@ date: 20250111
202 = انتقال فایل ها 202 = انتقال فایل ها
203 = ایجاد پروژه 203 = ایجاد پروژه
204 = تغییر پروژه 204 = تغییر پروژه
205 = ایجاد پایگاه داده 205 = ایجاد پایگاه داده
206 = تغییر رمز روت 206 = تغییر رمز روت
207 = ایمیل گیر 207 = ایمیل گیر
@@ -124,7 +125,7 @@ date: 20250111
604 = در حال استخراج 604 = در حال استخراج
605 = استخراج شد 605 = استخراج شد
606 = تارنما زیبا ایجاد گردید 606 = تارنما زیبا ایجاد گردید
607 = ایجاد سریع 607 = ایجاد سزیع
608 = نام وب سایت 608 = نام وب سایت
609 = لطفا نام پروژه را مشخص فرمائید! 609 = لطفا نام پروژه را مشخص فرمائید!
610 = ایجاد شد %s! 610 = ایجاد شد %s!
@@ -251,43 +252,11 @@ date: 20250111
# Setup # Setup
900 = لاراگون بسیار سریع اجرا می شود و دارای ردپای کمی در حافظه میباشد (< 4 MB) 900 = لاراگون بسیار سریع اجرا می شود و دارای ردپای کمی در حافظه میباشد (< 4 MB)
901 = برنامه شما URL زیبا را دریافت می کند ---> https://app.test 901 = برنامه شما URL زیبا را دریافت می کند ---> http://app.test
902 = اضافه کردن Notepad++ و ترمینال به منوی راست کلیک 902 = اضافه کردن Notepad++ و ترمینال به منوی راست کلیک
903 = راه های سریع برای باز کردن ویرایشگر متن و خط فرمان 903 = راه های سریع برای باز کردن ویرایشگر متن و خط فرمان
904 = فایل READMe را مشاهده کنید 904 = فایل READMe را مشاهده کنید
905 = اجرا لاراگون 905 = اجرا لاراگون
# SSL # SSL
906 = تولید خودکار گواهی SSL 906 = تولید خودکار گواهی SSL
# Version 3
140 = در حال مقدار دهی اولیه داده ها...
141 = داده ها را نمی توان مقداردهی اولیه کرد، لطفا دوباره امتحان کنید!
142 = منطقه
150 = افزودن لاراگون به Path
151 = حذف لاراگون از Path
152 = مدیریت Path
153 = لاراگون به Path اضافه شد! برای اعمال تغییرات ممکن است لازم باشد از سیستم خارج شوید و دوباره وارد شوید.
154 = لاراگون از Path حذف شد!
155 = بستن همه
156 = اجرای خودکار
157 = توقف اجرای سرویس ها...
158 = کمک
# Version 3.1.3
159 = کد QR خودکار تولید شده
# Version 3.3.1
160 = SSL فعال است. برای غیرفعال کردن کلیک کنید
161 = افزودن laragon.crt را به Trust Store
162 = مدیرت گواهی
163 = تنظیمات سریع
164 = چگونه "%s" را مدیریت کنیم
165 = چگونه Xdebug را به لاراگون اضافه کنیم
166 = WildcardDNS
167 = این چیست؟
# Version 3.5
920 = کلون
921 = پروژه ای را برای کلون کردن انتخاب کنید
922 = پایگاه داده کلون شده!

View File

@@ -1,6 +1,6 @@
-------------------------------------------------------- --------------------------------------------------------
version: 2.0.4 version: 2.0.4
author: Błażej Hap - blazejhap@gmail.com - https://conit-group.pl author: Błażej Hap - blazejhap@gmail.com - http://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 ---> https://app.test 901=Twoja aplikacja będzie dostępna pod wygodnym adresem ---> http://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 ---> https://app.test 901 = Seu aplicativo receberá um URL bonito ---> http://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 ---> https://app.test 901 = Ваше приложение получит удобный URL ---> http://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 ---> https://app.test 901 = Vaša aplikacija bo dobila lep URL ---> http://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 ---> https://app.test 901 = Din app kommer få vackra länkar ---> http://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

@@ -1,321 +0,0 @@
--------------------------------------------------------
version: 8.0.0
author: jaideejung007
date: 20250724
--------------------------------------------------------
# Main Interface
100 = เริ่มทั้งหมด
101 = เว็บ
102 = ฐานข้อมูล
103 = Terminal
104 = Root
105 = หยุด
106 = กำลังหยุด...
107 = รีโหลด
108 = เริ่ม
109 = เวอร์ชัน
110 = เปิดใช้งาน
111 = หยุดทั้งหมด
112 = ปิด
113 = ย่อ
114 = ขยาย
115 = ใช่
116 = ไม่
117 = ยกเลิก
118 = ตกลง
119 = เปิด
120 = ปิด
121 = เมนู
122 = หากคุณมีคำถาม โปรดติดต่อ
# Menu
199 = www
200 = เครื่องมือ
201 = Path
202 = ถ่ายโอนไฟล์
203 = สร้างโปรเจกต์
204 = สลับโปรเจกต์
205 = สร้างฐานข้อมูล
206 = เปลี่ยนรหัสผ่าน root
207 = Mail Catcher
208 = ดูอีเมลล่าสุด
209 = เปิดโฟลเดอร์อีเมล
210 = คัดลอก sendmail_path
211 = การกำหนดค่า
212 = ตัวส่งอีเมล
213 = ส่วนขยาย
214 = ผู้ดูแลเว็บ
215 = ล็อกอิน
216 = การตั้งค่า
217 = ออก
218 = ชื่อโปรเจกต์
# Preferences
300 = ทั่วไป
301 = เซอร์วิส && พอร์ต
310 = รัน Laragon เมื่อ Windows เริ่มทำงาน
311 = รัน Laragon อัตโนมัติเมื่อ Windows เริ่มทำงาน
312 = รันแบบย่อหน้าต่าง
# \n for a new line
313 = ย่อ Laragon ไปที่ System Tray\nคลิกซ้ายที่ไอคอนของ Laragon ใน System Tray เพื่อแสดง Laragon
314 = เริ่มทั้งหมดอัตโนมัติ
315 = เริ่มเซอร์วิสที่เลือกทั้งหมดโดยอัตโนมัติเมื่อ Laragon รัน
316 = ภาษา
317 = Document Root
318 = คลิกเพื่อเปลี่ยน Document Root
319 = ไดเรกทอรีข้อมูล
320 = คลิกเพื่อเปลี่ยน DataDir ของ MySQL
322 = สร้าง Virtual Hosts อัตโนมัติ
323 = เพียงวางโฟลเดอร์ใน Document Root และรีโหลด Apache Laragon จะสร้างชื่อโฮสต์ที่สอดคล้องกันในไฟล์ hosts และ Virtual Hosts ของ Apache ให้โดยอัตโนมัติ
# %s for a string placeholder
324 = ชื่อโฮสต์
325 = รูปแบบชื่อโฮสต์\nตัวอย่าง: ถ้าชื่อโปรเจกต์ของคุณคือ %s
328 = ขั้นสูง
329 = เมื่อฟังก์ชัน mail() ถูกเรียก Laragon จะแสดงข้อมูลอีเมล\nในหน้าต่างเล็กๆ ที่มุมขวาล่างของหน้าจอ
330 = หน้าต่างจะแสดงเป็นเวลา
331 = ฟีเจอร์นี้ช่วยให้คุณตรวจสอบเนื้อหาอีเมลได้อย่างรวดเร็ว\nคุณยังสามารถดูเนื้อหาของอีเมลล่าสุดได้ทาง:\nเมนู > PHP > MailCatcher
340 = ชื่อบัญชี Gmail
341 = รหัสผ่านบัญชี Gmail
342 = ทดสอบการส่งอีเมล
343 = คุณอาจต้องอนุญาต "การเข้าถึงของแอปที่มีความปลอดภัยน้อย" ในบัญชี Google ของคุณ\nรหัสผ่าน Gmail ของคุณจะถูกเข้ารหัส\nเมื่อเปิดใช้งาน คุณสามารถส่งอีเมลได้อย่างง่ายดายด้วยโค้ดเพียงบรรทัดเดียว:
# Mail Analyzer
350 = ตัววิเคราะห์อีเมล
351 = ส่งอีเมลทดสอบไปที่
352 = ทดสอบอีกครั้ง
353 = ทดสอบการส่งอีเมลอีกครั้ง คุณสามารถป้อนที่อยู่อีเมลอื่นเพื่อทดสอบได้
354 = ปิด
# System Tray
400 = Laragon ถูกย่อไว้ที่นี่
401 = สลับไปยังโปรเจกต์:
402 = สร้างฐานข้อมูลแล้ว
403 = เปลี่ยนรหัสผ่าน root ของ MySQL สำเร็จแล้ว
404 = รีโหลด Apache แล้ว
405 = Path ไม่ถูกต้อง
406 = ตรวจพบโปรเจกต์ใหม่\nLaragon จะเรียก nodejs เพื่อสร้าง Virtual Hosts ให้คุณ
# Hint
500 = ช่วยเหลือออนไลน์
501 = คลิกซ้าย: เปิด Laragon - คลิกขวา: เมนู
502 = หน้าเริ่มต้น
503 = การจัดการฐานข้อมูล
504 = เปิด Terminal (Cmder)
505 = Laragon จะเรียก nodejs เพื่อสร้าง Virtual Hosts ให้คุณ\nหากคุณต้องการฟีเจอร์นี้โดยไม่ต้องเรียก nodejs:\nรัน Laragon ในฐานะ Administrator
506 = Document Root
# Quick create website/project
600 = กำลังสร้าง
601 = สร้างแล้ว
602 = กำลังดาวน์โหลด
603 = ดาวน์โหลดแล้ว
604 = กำลังแตกไฟล์
605 = แตกไฟล์แล้ว
606 = สร้าง URL แบบอ่านง่ายแล้ว
607 = แอปด่วน
608 = ชื่อเว็บไซต์
609 = กรุณาระบุชื่อโปรเจกต์
610 = สร้าง %s สำเร็จแล้ว
611 = ไม่สามารถสร้าง %s ได้ เหตุผล: %s
612 = สำรวจ
613 = คลิกเพื่อไปยังโฟลเดอร์ของโปรเจกต์
614 = คลิกเพื่อเยี่ยมชมเว็บไซต์
# Messages
700 = sendmail_path ถูกคัดลอกไปยังคลิปบอร์ดแล้ว
701 = ฟีเจอร์นี้ไม่พร้อมใช้งานบนคอมพิวเตอร์ของคุณ
702 = กรุณาเริ่ม %s ก่อน
703 = ชื่อไม่ถูกต้อง
704 = ไดเรกทอรีนี้ไม่มีโปรเจกต์ Laravel ที่ถูกต้อง
705 = กรุณาเริ่ม PHP Server
706 = ไปที่ เมนู > การตั้งค่า > เซอร์วิส & พอร์ต และเปิดใช้งาน PHP Server
707 = มีโปรเจกต์นี้อยู่แล้ว
708 = หากคุณต้องการสร้างโปรเจกต์จริงๆ ให้ลบโฟลเดอร์ของโปรเจกต์แล้วลองอีกครั้ง
709 = ไม่มีโฟลเดอร์
710 = ไม่มีไฟล์
711 = %s ไม่ได้ทำงานอยู่ กรุณาเริ่ม Redis Server ก่อน
712 = Path ที่ติดตั้ง Laragon ไม่ควรมีช่องว่าง (เพื่อหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น)
713 = เซอร์วิส %s กำลังทำงานอยู่ แต่ภายใต้โปรเซสอื่น
714 = กรุณาหยุด WAMP stack ปัจจุบันของคุณ มิฉะนั้นการทำงานของ Laragon อาจไม่สามารถคาดเดาได้
715 = Path ของโปรเซส:
# Hope you never see these :)
716 = อุ๊ปส์! เกิดข้อผิดพลาดบางอย่าง...Laragon ตรวจพบข้อผิดพลาด exception:
717 = ไม่สามารถสร้างฐานข้อมูล %s ได้ เหตุผล: %s
718 = ไม่สามารถเปลี่ยนรหัสผ่าน root ของ MySQL ได้ เหตุผล: %s
719 = คุณต้องระบุที่อยู่ Gmail ที่ถูกต้อง
720 = ไม่สามารถสร้างทางลัดในโฟลเดอร์ Startup ได้
721 = ไม่สามารถลบทางลัดจากโฟลเดอร์ Startup ได้
722 = รูปแบบไม่ถูกต้อง ต้องมีรูปแบบชื่อโปรเจกต์เป็น {name}.xxx
723 = รูปแบบไม่ถูกต้อง ไม่ใช่ชื่อโฮสต์ที่ถูกต้อง
724 = ไม่ใช่ Data Dir ของ MySQL ที่ถูกต้อง
725 = คุณต้องเปิดใช้งานเซอร์วิส Apache และ MySQL ใน เมนู > การตั้งค่า > เซอร์วิส & พอร์ต
# When Laragon cannot modify the hosts file
726 = อุ๊ปส์! ระบบของคุณป้องกันการแก้ไขไฟล์ hosts\nกรุณาตรวจสอบโปรแกรมป้องกันไวรัส หรือ Permissions ในแท็บ Security หรือตรวจสอบว่าไฟล์เป็นแบบอ่านอย่างเดียวหรือไม่\nLaragon จะปิดใช้งานฟีเจอร์ "สร้าง Virtual Hosts อัตโนมัติ" ชั่วคราว
727 = เพื่อให้ฟีเจอร์นี้ใช้งานได้ คุณสามารถลอง:\n1. ไปที่: %s\drivers\etc\n2. คลิกขวาที่ไฟล์ hosts และเอาเครื่องหมายถูกออกจากช่อง Read-only
728 = หมายเหตุ: Permissions ปัจจุบันของไฟล์ hosts:
# hosts file is Read-only
729 = อ่านอย่างเดียว
# Write permission in Security tab
730 = Security > Write
# MySQL
800 = ชื่อฐานข้อมูล
801 = รหัสผ่านใหม่
802 = รหัสผ่านปัจจุบัน
# Version 2
219 = Ngrok
220 = แชร์
221 = ลิงก์ Ngrok ถูกคัดลอกไปยังคลิปบอร์ดแล้ว
222 = Ngrok tunnel พร้อมแล้ว
223 = คลิกเพื่อแก้ไขไฟล์ hosts ในฐานะ Administrator ด้วยตนเอง
224 = เริ่มแล้ว
226 = กำลังคลายไฟล์
227 = คลายไฟล์แล้ว
228 = รูปแบบไม่รองรับ
229 = กรุณารอจนกว่าการแยกไฟล์จะเสร็จสมบูรณ์
230 = ลิงก์ไม่ถูกต้อง
231 = เกิดข้อผิดพลาดขณะดาวน์โหลด กรุณาลองอีกครั้ง
232 = เกิดข้อผิดพลาด บางทีลิงก์ดาวน์โหลดของคุณอาจไม่ถูกต้อง
233 = กรุณาตรวจสอบลิงก์และลองอีกครั้ง
234 = เยี่ยมชมเว็บไซต์
235 = ปิดและเยี่ยมชมเว็บไซต์
236 = แก้ไข
237 = สลับ Document Root
238 = เลือกอันอื่น
239 = มีฐานข้อมูลนี้อยู่แล้ว
240 = เว้นว่างไว้หากไม่ทราบ
241 = พอร์ต SSL ของ Apache ถูกปิดใช้งานโดยปริยาย ทำเครื่องหมายเพื่อเปิดใช้งาน
242 = สร้างใบรับรอง SSL แล้ว
243 = คุณต้องคลิก [%s] ก่อน
244 = สร้างฐานข้อมูลอัตโนมัติ
245 = วิธีบังคับให้ Wordpress ใช้ URL แบบสัมพัทธ์
246 = คลิกซ้าย
247 = คลิกขวา
248 = ที่ติดตั้ง Laragon
249 = ลบทั้งหมด [อัตโนมัติ]
250 = ไฟล์การตั้งค่า
251 = ไฟล์ Startup
252 = วิธีเพิ่ม %s เวอร์ชันอื่น
253 = Laragon กำลังทำงานอยู่แล้ว
# Reset & generate a random password for root
803 = รีเซ็ตและสร้างรหัสผ่านแบบสุ่มสำหรับ root
804 = คุณสามารถแก้ไขปัญหาได้โดยการรีเซ็ตรหัสผ่าน MySQL สำหรับ root ที่
805 = ตรวจจับว่า MySQL กำลังทำงานหรือไม่
806 = %s กำลังทำงานด้วย PID %d
807 = พบหนึ่งโปรเซส
808 = คุณต้องหยุดเซิร์ฟเวอร์ MySQL ก่อน
810 = เริ่มเซิร์ฟเวอร์ MySQL ด้วยตัวเลือก %s
811 = กำลังรีเซ็ตรหัสผ่าน root และสร้างรหัสผ่านแบบสุ่ม
812 = รีเซ็ตและสร้างรหัสผ่าน root ของ MySQL แล้ว
813 = คัดลอกไปยังคลิปบอร์ดแล้ว: %s
814 = เกิดข้อผิดพลาด %s
815 = กำลังหยุด MySQL - PID %d
816 = ไม่สามารถหยุด MySQL ที่กำลังทำงานอยู่ได้ - PID %d
817 = คุณอาจลองรีเซ็ตด้วยตนเอง: %s
818 = เสร็จสิ้น
# Windows Explorer's Context Menu - && is not typo
830 = เมนูคลิกขวา
831 = เพิ่ม Sublime Text && Terminal
832 = ลบ Sublime Text && Terminal
833 = แก้ไขด้วย Sublime Text
834 = เปิดโฟลเดอร์ใน Sublime Text
836 = กรุณารัน Laragon ในฐานะ Administrator แล้วลองอีกครั้ง
# Setup
900 = Laragon ทำงานเร็วมากและใช้หน่วยความจำน้อยมาก (< 10 MB)
901 = แอปของคุณจะได้รับ URL แบบอ่านง่าย ---> https://app.test
902 = เพิ่ม Sublime Text && Terminal ไปยังเมนูคลิกขวา
903 = วิธีเปิด Text Editor และ Command Prompt อย่างรวดเร็ว
904 = ดูไฟล์ README
905 = รัน Laragon
# SSL
906 = สร้างใบรับรอง SSL อัตโนมัติ
# Version 3
140 = กำลังเตรียมข้อมูลเริ่มต้น...
141 = ไม่สามารถเตรียมข้อมูลเริ่มต้นได้ โปรดลองอีกครั้ง
142 = ภูมิภาค
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 = โคลนฐานข้อมูลแล้ว
# version 7.0 Laragon 2025
927 = ลบโปรเจกต์
928 = โปรไฟล์
929 = โปรไฟล์ปัจจุบัน
930 = โปรไฟล์ใหม่
931 = ชื่อโปรไฟล์
932 = การดำเนินการ
940 = คุณต้องเปิดใช้งานและเริ่ม Mailpit
# version 8.0 Laragon 2025
168 = SSL ปิดใช้งานอยู่ คลิกเพื่อเปิดใช้งาน
360 = สำรองข้อมูลอัตโนมัติ
361 = Laragon จะสำรองข้อมูลในไดเรกทอรีข้อมูลของคุณโดยอัตโนมัติทุก 8 ชั่วโมง โดยจัดเก็บข้อมูลสำรองไว้ใน %s และเก็บเวอร์ชันล่าสุด 5 เวอร์ชันไว้เพื่อความปลอดภัย
362 = ช่วงเวลาสำรองข้อมูล
363 = ชั่วโมง
380 = อัปเดตอัตโนมัติ
381 = Laragon จะตรวจสอบ ดาวน์โหลด และกำหนดค่า PHP เวอร์ชันล่าสุดโดยอัตโนมัติ ทำให้สภาพแวดล้อมทันสมัยอยู่เสมออย่างง่ายดาย
382 = %s [%s] เวอร์ชันล่าสุดถูกเพิ่มไปยัง Laragon แล้ว
383 = %s [%s] มีเวอร์ชันใหม่พร้อมใช้งาน
260 = คัดลอกรหัสผ่าน root
261 = สำรองข้อมูลทุกฐานข้อมูล
262 = ฐานข้อมูล MySQL ทั้งหมดถูกสำรองไปยัง %s เรียบร้อยแล้ว
263 = รหัสผ่าน root ของ MySQL ถูกคัดลอกไปยังคลิปบอร์ดแล้ว

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 ---> https://app.test 901 = Uygulama adresleriniz ---> http://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 ---> https://app.test 901 = Ваш додаток отримає гарний URL ---> http://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 --> https://name.test 323=Đưa thư mục <name> vào Document Root, Laragon sẽ tạo link đẹp cho bạn --> http://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 ---> https://app.test 901=app của bạn sẽ có link đẹp ---> http://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

View File

@@ -1,10 +1,10 @@
Alias /adminer "C:/laragon/etc/apps/adminer/" Alias /adminer "C:/laragon/etc/apps/adminer/"
# to give access from outside # to give access from outside
# replace the lines # replace the lines
# #
# Require local # Require local
# #
# by # by
# #
# Require all granted # Require all granted
@@ -12,8 +12,8 @@ Alias /adminer "C:/laragon/etc/apps/adminer/"
<Directory "C:/laragon/etc/apps/adminer/"> <Directory "C:/laragon/etc/apps/adminer/">
Options Indexes FollowSymLinks MultiViews Options Indexes FollowSymLinks MultiViews
AllowOverride all AllowOverride all
Require local Require local
</Directory> </Directory>

View File

@@ -1,10 +1,10 @@
Alias /laragon "C:/laragon/etc/apps/laragon/" Alias /laragon "C:/laragon/etc/apps/laragon/"
# to give access from outside # to give access from outside
# replace the lines # replace the lines
# #
# Require local # Require local
# #
# by # by
# #
# Require all granted # Require all granted
@@ -12,18 +12,18 @@ Alias /laragon "C:/laragon/etc/apps/laragon/"
<Directory "C:/laragon/etc/apps/laragon/"> <Directory "C:/laragon/etc/apps/laragon/">
Options Indexes FollowSymLinks MultiViews Options Indexes FollowSymLinks MultiViews
AllowOverride None AllowOverride None
Require local Require local
</Directory> </Directory>
<Directory "C:/laragon/etc/apps/laragon/uploads/"> <Directory "C:/laragon/etc/apps/laragon/uploads/">
Options Indexes FollowSymLinks MultiViews Options Indexes FollowSymLinks MultiViews
AllowOverride None AllowOverride None
DirectoryIndex None.Always.Listing DirectoryIndex None.Always.Listing
Require local Require local
SetHandler none SetHandler none
SetHandler default-handler SetHandler default-handler

View File

@@ -1,9 +1,9 @@
Alias /memcached "C:/laragon/etc/apps/memcached/" Alias /memcached "C:/laragon/etc/apps/memcached/"
# to give access from outside # to give access from outside
# replace the lines # replace the lines
# #
# Require local # Require local
# #
# by # by
# #
@@ -13,7 +13,7 @@ Alias /memcached "C:/laragon/etc/apps/memcached/"
<Directory "C:/laragon/etc/apps/memcached/"> <Directory "C:/laragon/etc/apps/memcached/">
Options Indexes FollowSymLinks MultiViews Options Indexes FollowSymLinks MultiViews
AllowOverride all AllowOverride all
Require local Require local
</Directory> </Directory>

View File

@@ -1,10 +1,10 @@
Alias /phpmyadmin "C:/laragon/etc/apps/phpMyAdmin/" Alias /phpmyadmin "C:/laragon/etc/apps/phpMyAdmin/"
# to give access from outside # to give access from outside
# replace the lines # replace the lines
# #
# Require local # Require local
# #
# by # by
# #
# Require all granted # Require all granted
@@ -12,8 +12,8 @@ Alias /phpmyadmin "C:/laragon/etc/apps/phpMyAdmin/"
<Directory "C:/laragon/etc/apps/phpMyAdmin/"> <Directory "C:/laragon/etc/apps/phpMyAdmin/">
Options Indexes FollowSymLinks MultiViews Options Indexes FollowSymLinks MultiViews
AllowOverride all AllowOverride all
Require local Require local
</Directory> </Directory>

View File

@@ -1,9 +1,9 @@
Alias /redis "C:/laragon/etc/apps/phpredisAdmin/" Alias /redis "C:/laragon/etc/apps/phpredisAdmin/"
# to give access from outside # to give access from outside
# replace the lines # replace the lines
# #
# Require local # Require local
# #
# by # by
# #
@@ -13,7 +13,7 @@ Alias /redis "C:/laragon/etc/apps/phpredisAdmin/"
<Directory "C:/laragon/etc/apps/phpredisAdmin/"> <Directory "C:/laragon/etc/apps/phpredisAdmin/">
Options Indexes FollowSymLinks MultiViews Options Indexes FollowSymLinks MultiViews
AllowOverride all AllowOverride all
Require local Require local
</Directory> </Directory>

View File

@@ -8,7 +8,7 @@ FcgidInitialEnv TEMP "C:/Windows/Temp"
FcgidInitialEnv TMP "C:/Windows/Temp" FcgidInitialEnv TMP "C:/Windows/Temp"
FcgidInitialEnv windir "C:/Windows" FcgidInitialEnv windir "C:/Windows"
# 10 hrs: in case you have long running scripts, increase FcgidIOTimeout # 10 hrs: in case you have long running scripts, increase FcgidIOTimeout
FcgidIOTimeout 36000 FcgidIOTimeout 36000
FcgidConnectTimeout 16 FcgidConnectTimeout 16
FcgidMaxRequestsPerProcess 0 FcgidMaxRequestsPerProcess 0

View File

@@ -5,7 +5,7 @@ SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4 SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on SSLHonorCipherOrder on
SSLProtocol all -SSLv3 SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3 SSLProxyProtocol all -SSLv3
@@ -13,3 +13,5 @@ SSLProxyProtocol all -SSLv3
SSLSessionCache "shmcb:logs/ssl_scache(512000)" SSLSessionCache "shmcb:logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300 SSLSessionCacheTimeout 300

1934
etc/apps/adminer/index.php Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,198 @@
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

@@ -0,0 +1,258 @@
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

@@ -0,0 +1,254 @@
<?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

@@ -0,0 +1,28 @@
.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

@@ -0,0 +1,34 @@
<?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

@@ -0,0 +1,18 @@
<?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

@@ -0,0 +1,45 @@
<?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

@@ -0,0 +1,44 @@
<?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));

154
etc/apps/laragon/index.php Normal file
View File

@@ -0,0 +1,154 @@
<?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

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

View File

@@ -0,0 +1,68 @@
--------------------------------------------------------------------
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>.

149
etc/apps/memcached/README Normal file
View File

@@ -0,0 +1,149 @@
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

@@ -0,0 +1,24 @@
<?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

@@ -0,0 +1,900 @@
<?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.

View File

@@ -38,14 +38,14 @@ if exist "%USER_DIR%\user.cmd" (
echo :: call start-ssh-agent.cmd echo :: call start-ssh-agent.cmd
echo :: set PATH=%%USER_DIR%%\bin\whatever;%%PATH%% echo :: set PATH=%%USER_DIR%%\bin\whatever;%%PATH%%
echo. echo.
echo :: cmd /c start http://localhost echo :: cmd /c start http://localhost
echo. echo.
) > "%USER_DIR%\user.cmd" ) > "%USER_DIR%\user.cmd"
:: cd /d "%CMDER_ROOT%\..\..\www" :: cd /d "%CMDER_ROOT%\..\..\www"
rem rem
) )
:: Laragon End ------------------------------------------------------------------- :: Laragon End -------------------------------------------------------------------
exit /b 0 exit /b 0

View File

@@ -6,7 +6,7 @@ location /adminer {
location ~ ^/adminer/(.+\.php)$ { location ~ ^/adminer/(.+\.php)$ {
alias C:/laragon/etc/apps/adminer/$1; alias C:/laragon/etc/apps/adminer/$1;
fastcgi_pass php_upstream; fastcgi_pass php_upstream;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;

View File

@@ -12,7 +12,7 @@ location ~ /laragon/uploads/(.+)\.php$ {
location ~ ^/laragon/(.+\.php)$ { location ~ ^/laragon/(.+\.php)$ {
allow all; allow all;
alias C:/laragon/etc/apps/laragon/$1; alias C:/laragon/etc/apps/laragon/$1;
fastcgi_pass php_upstream; fastcgi_pass php_upstream;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;

View File

@@ -3,10 +3,10 @@ location /memcached {
alias C:/laragon/etc/apps/memcached/; alias C:/laragon/etc/apps/memcached/;
index index.php; index index.php;
} }
location ~ ^/memcached/(.+\.php)$ { location ~ ^/memcached/(.+\.php)$ {
alias C:/laragon/etc/apps/memcached/$1; alias C:/laragon/etc/apps/memcached/$1;
fastcgi_pass php_upstream; fastcgi_pass php_upstream;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;

View File

@@ -3,12 +3,12 @@ location /phpmyadmin {
alias C:/laragon/etc/apps/phpmyadmin/; alias C:/laragon/etc/apps/phpmyadmin/;
index index.php; index index.php;
} }
location ~ ^/phpmyadmin/(.+\.php)$ { location ~ ^/phpmyadmin/(.+\.php)$ {
alias C:/laragon/etc/apps/phpmyadmin/$1; alias C:/laragon/etc/apps/phpmyadmin/$1;
fastcgi_pass php_upstream; fastcgi_pass php_upstream;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;

View File

@@ -6,7 +6,7 @@ location /redis {
location ~ ^/redis/(.+\.php)$ { location ~ ^/redis/(.+\.php)$ {
alias C:/laragon/etc/apps/phpRedisAdmin/$1; alias C:/laragon/etc/apps/phpRedisAdmin/$1;
fastcgi_pass php_upstream; fastcgi_pass php_upstream;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_FILENAME $request_filename;

View File

@@ -173,9 +173,9 @@ class Memcached
protected $socket = null; protected $socket = null;
public function getVersion() { public function getVersion() {
return ['localhost:11211' => '1.4.5']; return ['localhost:11211' => '1.4.5'];
} }
//may check: https://raw.githubusercontent.com/GoogleCloudPlatform/python-compat-runtime/master/appengine-compat/exported_appengine_sdk/php/sdk/google/appengine/runtime/Memcached.php //may check: https://raw.githubusercontent.com/GoogleCloudPlatform/python-compat-runtime/master/appengine-compat/exported_appengine_sdk/php/sdk/google/appengine/runtime/Memcached.php
public function setMulti() { public function setMulti() {
@@ -185,7 +185,7 @@ class Memcached
//TODO //TODO
die('TODO'); die('TODO');
} }
/** /**
* Add a serer to the server pool * Add a serer to the server pool
* *
@@ -444,7 +444,7 @@ class Memcached
/** /**
* Store an item. * Store an item.
* Fails if $key already exists * Fails if $key already exists
* *
* @param string $key * @param string $key
@@ -464,7 +464,7 @@ class Memcached
if ('STORED' == $s) { if ('STORED' == $s) {
$this->resultCode = Memcached::RES_SUCCESS; $this->resultCode = Memcached::RES_SUCCESS;
$this->resultMessage = ''; $this->resultMessage = '';
return true; return true;
} else { } else {

Binary file not shown.

View File

@@ -9,6 +9,7 @@
; PWD: Current working directory - where the COMMANDS run ; PWD: Current working directory - where the COMMANDS run
# Examples: # Examples:
; My Cool App: autorun node start $PORT PORT=9000 env_file=usr\my_file.env PWD=usr/proj/myapp DB_HOST=1.2.3.4 DB_PORT=9999 DB_USER=user DB_PASS="!$Ab.cs3cre1" DB_NAME=cooldb ; My Cool App: autorun node start $PORT PORT=9000 env_file=usr\my_file.env PWD=usr/proj/myapp DB_HOST=1.2.3.4 DB_PORT=9999 DB_USER=user DB_PASS="!$Ab.cs3cre1" DB_NAME=cooldb
; Awesome Tool: "PATH HAS SPACES SHOULD BE QUOTED LIKE THIS" ; Awesome Tool: "PATH HAS SPACES SHOULD BE QUOTED LIKE THIS"
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View File

@@ -9,6 +9,7 @@
; PWD: Current working directory - where the COMMANDS run ; PWD: Current working directory - where the COMMANDS run
# Examples: # Examples:
; My Cool App: autorun node start $PORT PORT=9000 env_file=usr\my_file.env PWD=usr/proj/myapp DB_HOST=1.2.3.4 DB_PORT=9999 DB_USER=user DB_PASS="!$Ab.cs3cre1" DB_NAME=cooldb ; My Cool App: autorun node start $PORT PORT=9000 env_file=usr\my_file.env PWD=usr/proj/myapp DB_HOST=1.2.3.4 DB_PORT=9999 DB_USER=user DB_PASS="!$Ab.cs3cre1" DB_NAME=cooldb
; Awesome Tool: "PATH HAS SPACES SHOULD BE QUOTED LIKE THIS" ; Awesome Tool: "PATH HAS SPACES SHOULD BE QUOTED LIKE THIS"
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View File

@@ -1,33 +1,25 @@
# 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/archives/php-8.4.3-nts-Win32-vs17-x64.zip *PHP-8.4=https://windows.php.net/downloads/releases/php-8.4.2-nts-Win32-vs17-x64.zip
*PHP-8.3=https://windows.php.net/downloads/releases/archives/php-8.3.16-nts-Win32-vs16-x64.zip *PHP-8.3=https://windows.php.net/downloads/releases/php-8.3.15-nts-Win32-vs16-x64.zip
*PHP-8.2=https://windows.php.net/downloads/releases/archives/php-8.2.26-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.1=https://windows.php.net/downloads/releases/archives/php-8.1.30-nts-Win32-vs16-x64.zip *PHP-8.1=https://windows.php.net/downloads/releases/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
Apache-2.4.57=https://www.apachelounge.com/download/VS16/binaries/httpd-2.4.57-win64-VS16.zip
Nginx-1.27.4=https://nginx.org/download/nginx-1.27.4.zip
--- ---
# Node.js # Node.js
# https://nodejs.org/en/download/prebuilt-binaries/current # https://nodejs.org/en/download/prebuilt-binaries/current
node-23.9=https://nodejs.org/dist/v23.9.0/node-v23.9.0-win-x64.zip node-23=https://nodejs.org/dist/v23.4.0/node-v23.4.0-win-x64.zip
node-22.14=https://nodejs.org/dist/v22.14.0/node-v22.14.0-win-x64.zip node-22=https://nodejs.org/dist/v22.12.0/node-v22.12.0-win-x64.zip
--- ---
# phpMyAdmin # phpMyAdmin
# After download, visit -> http://localhost/phpmyadmin # After download, visit -> http://localhost/phpmyadmin
phpmyadmin-6.0snapshot=https://files.phpmyadmin.net/snapshots/phpMyAdmin-6.0+snapshot-english.tar.xz phpmyadmin=https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-all-languages.zip
phpmyadmin=https://files.phpmyadmin.net/phpMyAdmin/5.2.2/phpMyAdmin-5.2.2-english.zip
# DB Tools # DB Tools
DBeaver=https://dbeaver.io/files/dbeaver-ce-latest-win32.win32.x86_64.zip DBeaver=https://dbeaver.io/files/dbeaver-ce-latest-win32.win32.x86_64.zip
@@ -51,7 +43,7 @@ postgresql-15.10=https://sbp.enterprisedb.com/getfile.jsp?fileid=1259300
--- ---
# MongoDB # MongoDB
# https://www.mongodb.com/try/download/community # https://www.mongodb.com/try/download/community
#mongodb-8=https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-8.0.4.zip #mongodb-8=https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-8.0.4.zip
#mongodb-7=https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-7.0.14.zip #mongodb-7=https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-7.0.14.zip
@@ -64,10 +56,8 @@ code=https://go.microsoft.com/fwlink/?Linkid=850641
--- ---
# Golang # Golang
# https://go.dev/dl/ # https://go.dev/dl/
go-1.24=https://go.dev/dl/go1.24.1.windows-amd64.zip golang-1.23=https://go.dev/dl/go1.23.4.windows-amd64.zip
go-1.23=https://go.dev/dl/go1.23.4.windows-amd64.zip
# Pocketbase # Pocketbase
# https://github.com/pocketbase/pocketbase/releases # https://github.com/pocketbase/pocketbase/releases
pocketbase=https://github.com/pocketbase/pocketbase/releases/download/v0.25.9/pocketbase_0.25.9_windows_amd64.zip pocketbase=https://github.com/pocketbase/pocketbase/releases/download/v0.23.7/pocketbase_0.23.7_windows_amd64.zip

View File

@@ -1,15 +1,15 @@
Simplicity is the ultimate sophistication. - Leonardo da Vinci Simplicity is the ultimate sophistication. - Leonardo da Vinci
Success is going from failure to failure without losing your enthusiasm. - Winston Churchill Success is going from failure to failure without losing your enthusiasm. - Winston Churchill
The journey of a thousand miles begins with one step. - Lao Tzu The journey of a thousand miles begins with one step. - Lao Tzu
Dream big and dare to fail. - Norman Vaughan Dream big and dare to fail. - Norman Vaughan
The power of imagination makes us infinite. - John Muir The power of imagination makes us infinite. - John Muir
Make each day your masterpiece. - John Wooden Make each day your masterpiece. - John Wooden
Believe and act as if it were impossible to fail. - Charles Kettering Believe and act as if it were impossible to fail. - Charles Kettering
Light tomorrow with today. - Elizabeth Barrett Browning Light tomorrow with today. - Elizabeth Barrett Browning
Even if you're on the right track, you'll get run over if you just sit there. - Will Rogers Even if you're on the right track, you'll get run over if you just sit there. - Will Rogers
Believe you can and you're halfway there. - Theodore Roosevelt Believe you can and you're halfway there. - Theodore Roosevelt
Don't wait. The time will never be just right. - Napoleon Hill Don't wait. The time will never be just right. - Napoleon Hill
A year from now you may wish you had started today. - Karen Lamb A year from now you may wish you had started today. - Karen Lamb
It is never too late to be what you might have been. - George Eliot It is never too late to be what you might have been. - George Eliot
If there is no struggle, there is no progress. - Frederick Douglass If there is no struggle, there is no progress. - Frederick Douglass
What we fear doing most is usually what we most need to do. - Tim Ferriss What we fear doing most is usually what we most need to do. - Tim Ferriss

View File

@@ -2,32 +2,5 @@
AutoCreateDatabase=true AutoCreateDatabase=true
Cached=true Cached=true
# Blank: an empty project
Blank=
# WordPress # WordPress
WordPress=https://wordpress.org/latest.tar.gz WordPress=https://wordpress.org/latest.zip
------------------------------------------------------
# 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,105 +1,167 @@
<?php <?php
if (!empty($_GET['q'])) { if (!empty($_GET['q'])) {
$query = htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8'); switch ($_GET['q']) {
case 'info':
switch ($query) { phpinfo();
case 'info': exit;
phpinfo(); break;
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 charset="UTF-8"> <meta http-equiv="Content-Type" content="text/html;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">
<style> <link rel="shortcut icon" href="https://i.imgur.com/ky9oqct.png" type="image/png">
html, body { <style>
height: 100%; *,
margin: 0; :before *,
padding: 0; :after * {
font-family: 'Karla', sans-serif; box-sizing: border-box;
font-weight: 100; }
background-color: #f9f9f9;
color: #333;
}
.container { body {
display: flex; margin: 0;
justify-content: center; min-height: 100vh;
align-items: center; font-weight: 100;
height: 100%; font-family: 'Karla', sans-serif;
text-align: center; font-size: 18px;
} }
.content { header,
max-width: 800px; main,
padding: 100px; nav,
background: #fff; aside {
border-radius: 8px; padding: 1rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin: auto;
} max-width: 1200px;
text-align: center;
}
.title { header {
font-size: 60px; display: flex;
margin: 0; flex-wrap: wrap;
} justify-content: center;
align-items: center;
}
.info { .header__item {
margin-top: 20px; margin: 0;
font-size: 18px; padding: 1rem;
line-height: 1.6; }
}
.info a { .header--logo {
color: #007bff; height: 8rem;
text-decoration: none; }
}
.info a:hover { h1 {
color: #0056b3; font-size: 5rem;
text-decoration: underline; }
}
.opt { main {
margin-top: 30px; background-color: #f5f5f5;
} }
.opt a { nav {
font-size: 18px; width: 100%;
color: #007bff; }
text-decoration: none;
}
.opt a:hover { ul {
color: #0056b3; list-style: none;
text-decoration: underline; padding: 0;
} 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>
<div class="container"> <header>
<div class="content"> <img class="header__item header--logo" src="https://i.imgur.com/ky9oqct.png" alt="Offline">
<h1 class="title" title="Laragon">Laragon</h1> <h1 class="header__item header--title" title="Laragon">Laragon</h1>
<div class="info"> </header>
<p><?php echo htmlspecialchars($_SERVER['SERVER_SOFTWARE'], ENT_QUOTES, 'UTF-8'); ?></p> <main>
<p>PHP version: <?php echo htmlspecialchars(phpversion(), ENT_QUOTES, 'UTF-8'); ?> <p>
<a title="phpinfo()" href="/?q=info">info</a> <?php print($_SERVER['SERVER_SOFTWARE']); ?>
</p> </p>
<p>Document Root: <?php echo htmlspecialchars($_SERVER['DOCUMENT_ROOT'], ENT_QUOTES, 'UTF-8'); ?></p> <p>
</div> PHP version: <?php print PHP_VERSION; ?> <span><a title="phpinfo()" href="/?q=info">info</a></span>
<div class="opt"> </p>
<p><a title="Getting Started" href="https://laragon.org/docs">Getting Started</a></p> <p>
</div> Document Root: <?php print($_SERVER['DOCUMENT_ROOT']); ?>
</div> </p>
</div> <p>
<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>