├── .gitignore ├── .htaccess ├── LICENSE ├── README.md ├── api ├── index.php └── set.php ├── asset ├── .gitkeep ├── css │ └── main.css └── js │ └── app.js ├── config.php ├── inc ├── class │ ├── database.db │ ├── db.class.php │ └── url.class.php ├── functions.php ├── index.php └── require.php ├── index.php └── info.php /.gitignore: -------------------------------------------------------------------------------- 1 | # CakePHP 3 2 | 3 | /vendor/* 4 | /config/app.php 5 | 6 | /tmp/cache/models/* 7 | !/tmp/cache/models/empty 8 | /tmp/cache/persistent/* 9 | !/tmp/cache/persistent/empty 10 | /tmp/cache/views/* 11 | !/tmp/cache/views/empty 12 | /tmp/sessions/* 13 | !/tmp/sessions/empty 14 | /tmp/tests/* 15 | !/tmp/tests/empty 16 | 17 | /logs/* 18 | !/logs/empty 19 | 20 | # CakePHP 2 21 | 22 | /app/tmp/* 23 | /app/Config/core.php 24 | /app/Config/database.php 25 | /vendors/* 26 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | Options -Indexes 2 | order deny,allow 3 | 4 | 5 | deny from all 6 | 7 | 8 | 9 | deny from all 10 | 11 | 12 | RewriteEngine On 13 | RewriteCond $1 !^(api|asset) 14 | RewriteRule ^(\d+|\w+)$ index.php?id=$1 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Cyril Wong 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 短网址 2 | --- 3 | > 一个支持域名网址缩短的服务,这里是它的源代码。 4 | 5 | [**☞ Live Preview**](http://ins.si) 6 | 7 | ## 概述 8 | YSurl 是一个网址缩短服务的网站,这是它的源代码。 9 | 10 | ## 修改 11 | 12 | 在原来的基础上增加自适应移动端,随机ACG背景 13 | 14 | ## 安装 15 | YSurl 基于 PHP、SQLite 进行开发,您只需要修改 `config.php` 的相关配置并把 inc 目录权限设置为可读写即可。 16 | 17 | 对于 `Nginx` 用户,则还需把 `nginx.txt` 里面的内容添加到 Nginx 的配置文件里。 18 | 19 | 添加伪静态 20 | 21 | ``` 22 | location / { 23 | try_files $uri $uri/ =404; 24 | rewrite (\d+|\w+)$ /index.php?id=$1; 25 | 26 | location ^~ /asset/ { 27 | root /var/www/crz.im; 28 | } 29 | 30 | location ^~ /api/ { 31 | root /var/www/crz.im; 32 | } 33 | 34 | location ^~ /inc/ { 35 | return 403; 36 | } 37 | } 38 | ``` 39 | 40 | ## 鸣谢 41 | 42 | YSurl 项目 Fork 自 [CRZ.im](https://github.com/Caringor/CRZ.im/) 43 | 44 | License
45 | Unless otherwise stated, everything on this GitHub is released under the [MIT](https://cyrilwong.mit-license.org/) license. 46 | -------------------------------------------------------------------------------- /api/index.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/set.php: -------------------------------------------------------------------------------- 1 | set_url($request_arr['url'], $config['length']); 21 | } else if(strstr($request_arr['url'], $_SERVER['HTTP_HOST'])) { 22 | $opt['content'] = '链接已经是短地址了。'; 23 | } else if(!$is_link) { 24 | $opt['content'] = '请输入正确格式的网址。'; 25 | } 26 | } else { 27 | $opt['content'] = '调用参数不能为空。'; 28 | } 29 | 30 | echo json_encode($opt); 31 | 32 | ?> -------------------------------------------------------------------------------- /asset/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nov23e/YSurl/436ef783bd0da7600684e0ed347ae333e4f5a185/asset/.gitkeep -------------------------------------------------------------------------------- /asset/css/main.css: -------------------------------------------------------------------------------- 1 | /* Reset */ 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | html, body, input, text, textarea { 7 | outline: none; 8 | font-family: 'Arial', 'Microsoft YaHei', '黑体', '宋体', sans-serif; 9 | font-size: 12px; 10 | } 11 | html, body { 12 | background: #fff; 13 | } 14 | a { 15 | text-decoration: none; 16 | } 17 | a:hover { 18 | text-decoration: underline; 19 | } 20 | 21 | /* Main */ 22 | .wrap { 23 | text-align: center; 24 | overflow: hidden; 25 | } 26 | .wrap .meta { 27 | margin: 160px 0 0 0; 28 | opacity: 0; 29 | transform: translateY(-150px); 30 | transition: .5s all ease; 31 | } 32 | .on .wrap .meta { 33 | opacity: 1; 34 | transform: translateY(0); 35 | } 36 | .wrap .meta .title { 37 | line-height: 1em; 38 | color: #ff4665; 39 | font-size: 42px; 40 | text-transform: uppercase; 41 | } 42 | .wrap .meta .description { 43 | margin: 10px 0 0 0; 44 | line-height: 1em; 45 | color: #7e7e7e; 46 | font-size: 16px; 47 | font-weight: normal; 48 | } 49 | .wrap .link-area { 50 | margin: 50px 0 0 0; 51 | opacity: 0; 52 | transition: .5s opacity ease; 53 | } 54 | .on .wrap .link-area { 55 | opacity: 1; 56 | } 57 | .wrap .link-area input { 58 | display: inline-block; 59 | vertical-align: middle; 60 | } 61 | .wrap .link-area #url { 62 | width: 320px; 63 | height: 32px; 64 | line-height: 32px; 65 | padding: 0 10px; 66 | border: 3px solid #bdc3c7; 67 | border-radius: 5px; 68 | color: #333; 69 | } 70 | .wrap .link-area #url.focus, 71 | .wrap .link-area #url:focus { 72 | border-color: #ff4665; 73 | transition: .2s border ease; 74 | } 75 | .wrap .link-area #submit { 76 | width: 90px; 77 | height: 38px; 78 | margin: 0 0 0 5px; 79 | background: #ff4665; 80 | border-radius: 5px; 81 | color: #fff; 82 | border: none; 83 | cursor: pointer; 84 | transition: .2s opacity ease; 85 | } 86 | .wrap .link-area #submit:hover { 87 | opacity: .75; 88 | } 89 | .wrap .link-area #submit:active { 90 | opacity: .9; 91 | } 92 | .wrap .footer { 93 | width: 100%; 94 | bottom: 80px; 95 | left: 0; 96 | position: absolute; 97 | color: #7e7e7e; 98 | } 99 | .wrap .footer a { 100 | color:#ff4665; 101 | } -------------------------------------------------------------------------------- /asset/js/app.js: -------------------------------------------------------------------------------- 1 | 2 | var APP = (function(){ 3 | 4 | var fn = { 5 | 6 | // 生成短地址 7 | setUrl: function(self) { 8 | var urlEl = document.getElementById('url'), 9 | tips = 'https://', 10 | request = { 11 | "url": urlEl.value 12 | }; 13 | fn.getJson('api/set.php', true, JSON.stringify(request), function(res) { 14 | if(res.success == 'true') { 15 | urlEl.className = 'focus'; 16 | urlEl.value = res.content.url; 17 | } else { 18 | urlEl.className = ''; 19 | urlEl.value = ''; 20 | urlEl.setAttribute('placeholder', res.content); 21 | setTimeout(function() { 22 | urlEl.setAttribute('placeholder', tips); 23 | }, 2000); 24 | } 25 | }); 26 | }, 27 | 28 | // 获取 JSON 数据 29 | getJson: function(url, post, data, callback) { 30 | var xhr = new XMLHttpRequest(), 31 | type = (post) ? 'POST' : 'GET'; 32 | xhr.onreadystatechange = function() { 33 | if(xhr.readyState == 4 && xhr.status == 200) { 34 | var json = JSON.parse(xhr.responseText); 35 | callback(json); 36 | } else if(xhr.readyState == 4) { 37 | callback(false); 38 | } 39 | } 40 | xhr.open(type, url, true); 41 | xhr.send(data); 42 | } 43 | 44 | }, 45 | 46 | init = function() { 47 | setTimeout(function() { 48 | var el = document.getElementsByTagName('html')[0]; 49 | el.className = 'on'; 50 | }, 10); 51 | }; 52 | 53 | return { 54 | fn: fn, 55 | init: init 56 | } 57 | 58 | })(); 59 | 60 | 61 | document.addEventListener('DOMContentLoaded', function() { 62 | APP.init(); 63 | }) -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /inc/class/database.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nov23e/YSurl/436ef783bd0da7600684e0ed347ae333e4f5a185/inc/class/database.db -------------------------------------------------------------------------------- /inc/class/db.class.php: -------------------------------------------------------------------------------- 1 | db = new PDO('sqlite:' . dirname(__FILE__) . '/database.db'); 7 | $this->init_tab(); 8 | } 9 | 10 | // 初始化数据库结构 11 | function init_tab() { 12 | // 网址表 13 | $this->db->exec("CREATE TABLE urls( 14 | id char(8) PRIMARY KEY, 15 | url longtext, 16 | ip varchar(16), 17 | ua varchar(255) 18 | )"); 19 | } 20 | 21 | // 查询表内容 22 | function query($name, $rule = '') { 23 | $query = $this->db->prepare("SELECT * FROM $name $rule"); 24 | $query->execute(); 25 | $result = $query->fetchAll(); 26 | return $result; 27 | } 28 | 29 | // 插入表内容 30 | function insert($tab, $key, $val) { 31 | $exec = $this->db->exec("INSERT INTO $tab ($key) VALUES($val)"); 32 | if(!$exec) return false; 33 | $this->db->beginTransaction(); 34 | } 35 | 36 | // 删除表内容 37 | function delete($tab, $rule = '') { 38 | $exec = $this->db->exec("DELETE FROM $tab $rule"); 39 | if(!$exec) return false; 40 | $this->db->beginTransaction(); 41 | } 42 | 43 | } 44 | 45 | ?> -------------------------------------------------------------------------------- /inc/class/url.class.php: -------------------------------------------------------------------------------- 1 | db = $db_c; 8 | } 9 | 10 | // 生成短地址 11 | public function set_url($url, $size = 4) { 12 | $id = $this->get_id($url); 13 | if(!$id) { 14 | $id = $this->create_id($url, $size); 15 | $ip = get_ip(); 16 | $ua = get_ua(); 17 | $this->db->insert('urls', 'id, url, ip, ua', "'$id', '$url', '$ip', '$ua'"); 18 | } 19 | $s_url = get_uri() . $id; 20 | return $s_url; 21 | } 22 | 23 | // 生成地址 ID 24 | public function create_id($url, $size = 4) { 25 | $md5 = md5($url); 26 | // 随机抽取 MD5 中的字符作为 ID 27 | $id = ''; 28 | for($i = 0; $i < $size; $i++) { 29 | $rand_id = rand(0, strlen($md5) - 1); 30 | $id .= $md5[$rand_id]; 31 | } 32 | // ID 检测 33 | if($this->has_id($id)) { 34 | return $this->create_id($url, $size); 35 | } else { 36 | return $id; 37 | } 38 | } 39 | 40 | // 查询 ID 号 41 | public function get_id($url) { 42 | $result = $this->db->query('urls', "WHERE url = '$url'"); 43 | (count($result) > 0) ? $opt = $result[0]['id'] : $opt = false; 44 | return $opt; 45 | } 46 | 47 | // 查询目标地址 48 | public function get_url($id) { 49 | $result = $this->db->query('urls', "WHERE id = '$id'"); 50 | (count($result) > 0) ? $opt = $result[0]['url'] : $opt = false; 51 | return $opt; 52 | } 53 | 54 | // 检测 ID 是否已经存在 55 | public function has_id($id) { 56 | $result = $this->db->query('urls', "WHERE id = '$id'"); 57 | (count($result) > 0) ? $opt = true : $opt = false; 58 | return $opt; 59 | } 60 | 61 | // 清空短地址 62 | public function clean_urls() { 63 | $del = $this->db->delete('urls'); 64 | if($del) return true; 65 | return false; 66 | } 67 | 68 | } 69 | 70 | ?> -------------------------------------------------------------------------------- /inc/functions.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /inc/index.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /inc/require.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | get_url($_GET['id']); 12 | // 重定向至目标网址 13 | if($url) { 14 | header('Location: ' . $url); 15 | exit; 16 | } 17 | 18 | } 19 | 20 | ?> 21 | 22 | 23 | 24 | 25 | 26 | 27 | <?php echo get_title() . ' - ' . get_description(); ?> 28 | 29 | 30 | 31 | 34 | 35 | 36 |
37 |
38 |

39 |

40 |
41 | 45 | 52 |
53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /info.php: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------