├── .htaccess ├── 404.html ├── LICENSE ├── README.md ├── _notes └── .htaccess ├── config.php ├── css ├── simple.css ├── simple.min.css ├── styles.css └── styles.min.css ├── favicon.ico ├── image ├── Screenshot_20230725_001749.png ├── Screenshot_20230725_001758.png ├── Screenshot_20230725_001834.png ├── Screenshot_20230725_001901.png ├── Screenshot_20230725_001922.png ├── Screenshot_20230725_002013.png ├── Screenshot_20230725_002105.png ├── Screenshot_20230725_002159.png ├── Screenshot_20230725_002735.png ├── Screenshot_20230725_003659.png └── Screenshot_20230725_003719.png ├── index.php ├── js ├── notelist.js ├── notelist.min.js ├── script.js ├── script.min.js ├── simple.js └── simple.min.js ├── modules ├── common.php ├── copy.php ├── create_notes_folder.php ├── css │ ├── lastsaved.css │ ├── lastsaved.min.css │ ├── menu.css │ ├── menu.min.css │ ├── modal.css │ └── modal.min.css ├── header.php ├── js │ ├── copy.js │ ├── copy.min.js │ ├── lastsaved.js │ ├── lastsaved.min.js │ ├── menu.js │ ├── menu.min.js │ ├── modal.js │ ├── modal.min.js │ ├── password.js │ ├── password.min.js │ ├── tinyago.js │ ├── tinyago.min.js │ ├── view.js │ └── view.min.js ├── lastsaved.php ├── menu.php ├── password.php ├── protect.php └── protect_form.php ├── nginx.conf.example ├── notelist.php ├── passwordHelp.html ├── setup.php ├── simple.php └── view.php /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | 3 | #RewriteCond %{HTTPS} off 4 | #RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L] 5 | 6 | # if there is a view parameter in the querystring then use view.php 7 | RewriteCond %{QUERY_STRING} ^view [NC] 8 | RewriteRule ^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)$ view.php?note=$1 [L,QSA] 9 | # the [L] flag will stop any futher processing 10 | 11 | RewriteCond %{QUERY_STRING} ^simple [NC] 12 | RewriteRule ^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)$ simple.php?note=$1 [L,QSA] 13 | # the [L] flag will stop any futher processing 14 | 15 | #allow 0-9 a-z and hyphens/dashes 16 | RewriteRule ^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)$ index.php?note=$1 [L,QSA] 17 | 18 | 19 | Header set X-Robots-Tag: "noindex, nofollow" 20 | 21 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | 2 | 404 Not Found 3 | 4 |

404 Not Found

5 |
nginx
6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 domOrielton 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 | # minimal-web-notepad 2 | 3 | 这是一个在 [pereorga/minimalist-web-notepad](https://github.com/pereorga/minimalist-web-notepad) 上添加了额外功能的分支。附加的代码使得体积增加了,所以不再是极简,但是在经过压缩和gzip后仅有10KB。如果你想要真正极简的版本,pereorga 的实现小于 3KB,而且还没有经过压缩! 4 | 5 | 密码功能是通过在文本文件中添加一个头部行来实现的,该行在便签中不显示。请注意,这并不会加密内容,只是限制访问权限。服务器的唯一要求是启用了 mod_rewrite 的 Apache Web 服务器或启用了 ngx_http_rewrite_module 和 PHP 的 nginx Web 服务器。 6 | 7 | ![编辑界面截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_001749.png) 8 | 9 | 对 pereorga 的原始版本添加了以下功能: 10 | - 可以在便签中显示超链接的查看选项(在移动设备上非常有用) 11 | - 支持密码保护,并提供只读访问选项 12 | - 仅查看链接 13 | - 显示便签的上次保存时间 14 | - 将便签的URL、只读URL和便签文本复制到剪贴板 15 | - 以无衬线字体或等宽字体查看便签 16 | - 可以下载便签 17 | - 显示可用的便签列表 18 | - 可以根据需要打开或关闭功能以减小页面大小 19 | 20 | 可以在 汉化版:https://7t.vc 或原版 http://note.rf.gd/ 或 http://note.rf.gd/some-note-name-here 上查看演示。由于演示没有启用 HTTPS,所以浏览器中会显示密码警告,请仅用于测试,不要用于其他用途。 21 | 22 | 截图: 23 | **便签查看模式** 24 | ![查看界面截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_001758.png) 25 | 26 | **适配移动设备的响应式菜单** 27 | ![移动菜单截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_003719.png) 28 | ![移动菜单截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_003659.png) 29 | 30 | **等宽字体** 31 | ![等宽字体截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_001901.png) 32 | 33 | **密码保护** 34 | ![密码保护截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_001922.png) 35 | 36 | **受保护便签的密码提示** 37 | ![密码提示截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_002013.png) 38 | 39 | “以只读模式查看”链接仅显示便签文本,不显示其他内容 40 | 41 | **复制到剪贴板的链接** 42 | ![复制截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_002105.png) 43 | 44 | **便签列表** 45 | - 通常仅用于非公开的 URL,尽管页面是受密码保护的 46 | ![便签列表截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_002159.png) 47 | 48 | 如果不想显示便签列表,可以在 index.php 文件顶部将 $allow_noteslist 参数设置为 false,或者将 `notelist.php` 重命名为其他名称。便签列表页面的密码位于 `notelist.php` 文件的顶部,可以使用 `Protect\with('modules/protect_form.php','在这里更改密码')` 进行修改。 49 | 50 | **备选编辑视图** 51 | 还有一种备选的编辑视图,可以在便签后添加 `?simple` 来访问,例如 /quick?simple。我个人觉得这个视图非常适合在手机上快速添加便签,它在页面顶部有一个较小的编辑区域,当你输入文本并按下回车键时,它会将文本添加到便签中,并将其移动到占据页面剩余部分的视图中。此视图部分将 URL 显示为可点击的链接。您不能在此视图上设置密码,但它会遵循已有的密码。 52 | 53 | ![复制截图](https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/master/image/Screenshot_20230725_002735.png) 54 | 55 | 安装: 56 | 只要启用了 mod_rewrite 并且 Web 服务器被允许写入 `_notes` 数据目录,就不需要进行任何配置。这个数据目录在 `config.php` 文件中设置,所以如果你想要将其更改为原始 pereorga/minimalist-web-notepad 版本使用的文件夹,请在那里进行修改。所有的便签都以文本文件的形式存储,所以运行 Apache(或 Nginx)的服务器应该就足够了,不需要使用数据库。如果便签无法保存,请检查 `_notes` 目录的权限,通常 0755 或 744 就足够了。 57 | 58 | ![权限截图](https://raw.github.com/domOrielton/minimal-web-notepad/screenshots/mn_permissions.png) 59 | 60 | 还有一个 `setup.php` 页面,可以用来检查 `_notes` 目录是否存在并且可以写入。如果无法保存便签,可以尝试删除 `_notes` 目录,然后访问 `setup.php` 页面以创建该文件夹。如果一切正常,可以选择删除 `setup.php` 文件。 61 | 62 | 可能有些情况下需要将 `config.php` 文件中的 $base_url 变量替换为您安装的硬编码 URL 路径。如果是这种情况,请将以 `$base_url=dirname('//')` 开头的行替换为 `$base_url='http://actualURL.com/notes'`,将 actualURL.com/notes 替换为与您的安装相关的内容。 63 | 64 | ### 在 Apache 上 65 | 可能需要启用 mod_rewrite 并在站点配置中设置 `.htaccess` 文件。请参阅 [在 Ubuntu 14.04 上设置 Apache 的 mod_rewrite](https://www.digitalocean.com/community/tutorials/how-to-set-up-mod_rewrite-for-apache-on-ubuntu-14-04)。 66 | 67 | ## 在 Nginx 上 68 | 在 Nginx 上,需要确保 nginx.conf 文件正确配置以确保应用程序按预期工作。请检查 nginx.conf.example 文件或查看[没有密码问题的讨论](https://github.com/domOrielton/minimal-web-notepad/issues/4)。感谢 [eonegh](https://github.com/eonegh) 提供示例文件。 69 | -------------------------------------------------------------------------------- /_notes/.htaccess: -------------------------------------------------------------------------------- 1 | Deny from all 2 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /css/simple.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | background: #ebeef1; 4 | } 5 | 6 | .container { 7 | position: absolute; 8 | top: 20px; 9 | right: 20px; 10 | bottom: 20px; 11 | left: 20px; 12 | } 13 | 14 | .contentAdd, .content { 15 | font-size: 100%; 16 | margin: 0; 17 | padding: 20px; 18 | overflow-y: auto; 19 | resize: none; 20 | width: 100%; 21 | height: 10%; 22 | min-height: 10%; 23 | -webkit-box-sizing: border-box; 24 | -moz-box-sizing: border-box; 25 | box-sizing: border-box; 26 | border: 1px #ddd solid; 27 | outline: none; 28 | font-family: sans-serif; 29 | } 30 | 31 | .content { 32 | height: 90%; 33 | min-height: 90%; 34 | } 35 | 36 | .content br { 37 | display: block; 38 | line-height: 1.5em; 39 | } 40 | 41 | @media screen and (max-width: 600px) { 42 | .contentAdd { 43 | padding-top: 5px !important; 44 | } 45 | } 46 | 47 | #printable { 48 | display: none; 49 | } 50 | 51 | @media print { 52 | .container { 53 | display: none; 54 | } 55 | 56 | #printable { 57 | display: block; 58 | white-space: pre-wrap; 59 | word-break: break-word; 60 | } 61 | } 62 | 63 | .wordwrap { 64 | /* used for the view functionality */ 65 | white-space: pre-wrap; 66 | /* CSS3 */ 67 | white-space: -moz-pre-wrap; 68 | /* Firefox */ 69 | white-space: -pre-wrap; 70 | /* Opera <7 */ 71 | white-space: -o-pre-wrap; 72 | /* Opera 7 */ 73 | word-wrap: break-word; 74 | /* IE */ 75 | } 76 | 77 | .footer { 78 | font-size: 100%; 79 | font-family: monospace; 80 | position: absolute; 81 | bottom: 0; 82 | left: 20px; 83 | text-align: left; 84 | } 85 | 86 | @media print { 87 | .footer { 88 | display: none; 89 | } 90 | } 91 | 92 | .navbar { 93 | overflow: hidden; 94 | position: fixed; 95 | bottom: 0; 96 | min-width: 100px; 97 | background-color: #ebeef1; 98 | } 99 | 100 | .navbar a { 101 | float: left; 102 | display: block; 103 | color: black; 104 | text-align: center; 105 | padding: 1px 5px; 106 | text-decoration: underline; 107 | } 108 | 109 | .navbar a:hover { 110 | /*background-color: #ddd;*/ 111 | color: black; 112 | } 113 | 114 | .navbar a.active { 115 | color: black; 116 | } 117 | -------------------------------------------------------------------------------- /css/simple.min.css: -------------------------------------------------------------------------------- 1 | body{margin:0;background:#ebeef1}.container{position:absolute;top:20px;right:20px;bottom:20px;left:20px}.contentAdd,.content{font-size:100%;margin:0;padding:20px;overflow-y:auto;resize:none;width:100%;height:10%;min-height:10%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px #ddd solid;outline:0;font-family:sans-serif}.content{height:90%;min-height:90%}.content br{display:block;line-height:1.5em}@media screen and (max-width:600px){.contentAdd{padding-top:5px!important}}#printable{display:none}@media print{.container{display:none}#printable{display:block;white-space:pre-wrap;word-break:break-word}}.wordwrap{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}.footer{font-size:100%;font-family:monospace;position:absolute;bottom:0;left:20px;text-align:left}@media print{.footer{display:none}}.navbar{overflow:hidden;position:fixed;bottom:0;min-width:100px;background-color:#ebeef1}.navbar a{float:left;display:block;color:black;text-align:center;padding:1px 5px;text-decoration:underline}.navbar a:hover{color:black}.navbar a.active{color:black} -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | /*! Minimalist Web Notepad | https://github.com/pereorga/minimalist-web-notepad */ 2 | body { 3 | margin: 0; 4 | background: #ebeef1; 5 | } 6 | 7 | .container { 8 | position: absolute; 9 | top: 20px; 10 | right: 20px; 11 | bottom: 20px; 12 | left: 20px; 13 | } 14 | 15 | .content { 16 | font-size: 100%; 17 | margin: 0; 18 | padding: 20px; 19 | overflow-y: auto; 20 | resize: none; 21 | width: 100%; 22 | height: 100%; 23 | min-height: 100%; 24 | -webkit-box-sizing: border-box; 25 | -moz-box-sizing: border-box; 26 | box-sizing: border-box; 27 | border: 1px #ddd solid; 28 | outline: none; 29 | /* comment font- settings out to return to default monospace font */ 30 | font-family: sans-serif; 31 | font-size: medium; 32 | } 33 | 34 | #printable { 35 | display: none; 36 | } 37 | 38 | .hidden {visibility: hidden;} 39 | 40 | a { 41 | cursor: pointer; 42 | color: blue; 43 | } 44 | 45 | a:hover, a.hover { 46 | text-decoration: underline; 47 | } 48 | 49 | @media print { 50 | #content { 51 | display: none; 52 | } 53 | 54 | #printable { 55 | display: block; 56 | white-space: pre-wrap; 57 | word-break: break-word; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /css/styles.min.css: -------------------------------------------------------------------------------- 1 | /*! Minimalist Web Notepad | https://github.com/pereorga/minimalist-web-notepad */body{margin:0;background:#ebeef1}.container{position:absolute;top:20px;right:20px;bottom:20px;left:20px}.content{font-size:100%;margin:0;padding:20px;overflow-y:auto;resize:none;width:100%;height:100%;min-height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px #ddd solid;outline:0;font-family:sans-serif;font-size:medium}#printable{display:none}.hidden{visibility:hidden}a{cursor:pointer;color:blue}a:hover,a.hover{text-decoration:underline}@media print{#content{display:none}#printable{display:block;white-space:pre-wrap;word-break:break-word}} 2 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/favicon.ico -------------------------------------------------------------------------------- /image/Screenshot_20230725_001749.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_001749.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_001758.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_001758.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_001834.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_001834.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_001901.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_001901.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_001922.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_001922.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_002013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_002013.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_002105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_002105.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_002159.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_002159.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_002735.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_002735.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_003659.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_003659.png -------------------------------------------------------------------------------- /image/Screenshot_20230725_003719.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VMCoud/minimal-web-notepad/4f38db2e2d9763ff49fd169e915a58bf51a6b971/image/Screenshot_20230725_003719.png -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | <?php print $_GET['note']; ?> 82 | 83 | 84 | 85 | 86 |
87 | 90 |
91 |

 92 | 	
 93 |   '.PHP_EOL;
100 |     echo "".PHP_EOL;
101 |   }
102 | 	if ($include_Header) { checkHeader($path, null, true); } //check if the removePassword be shown ?>
103 | 
104 | 
105 | 


--------------------------------------------------------------------------------
/js/notelist.js:
--------------------------------------------------------------------------------
 1 | // from https://www.w3schools.com/howto/howto_js_sort_table.asp
 2 | function sortTable(n) {
 3 |   var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
 4 |   table = document.getElementById("notelistTable");
 5 |   switching = true;
 6 |   //Set the sorting direction to ascending:
 7 |   dir = "asc";
 8 |   /*Make a loop that will continue until
 9 |   no switching has been done:*/
10 |   while (switching) {
11 |     //start by saying: no switching is done:
12 |     switching = false;
13 |     rows = table.getElementsByTagName("TR");
14 |     /*Loop through all table rows (except the
15 |     first, which contains table headers):*/
16 |     for (i = 1; i < (rows.length - 1); i++) {
17 |       //start by saying there should be no switching:
18 |       shouldSwitch = false;
19 |       /*Get the two elements you want to compare,
20 |       one from current row and one from the next:*/
21 |       x = rows[i].getElementsByTagName("TD")[n];
22 |       y = rows[i + 1].getElementsByTagName("TD")[n];
23 |       /*check if the two rows should switch place,
24 |       based on the direction, asc or desc:*/
25 |       if (dir == "asc") {
26 |         if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
27 |           //if so, mark as a switch and break the loop:
28 |           shouldSwitch = true;
29 |           break;
30 |         }
31 |       } else if (dir == "desc") {
32 |         if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
33 |           //if so, mark as a switch and break the loop:
34 |           shouldSwitch = true;
35 |           break;
36 |         }
37 |       }
38 |     }
39 |     if (shouldSwitch) {
40 |       /*If a switch has been marked, make the switch
41 |       and mark that a switch has been done:*/
42 |       rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
43 |       switching = true;
44 |       //Each time a switch is done, increase this count by 1:
45 |       switchcount++;
46 |     } else {
47 |       /*If no switching has been done AND the direction is "asc",
48 |       set the direction to "desc" and run the while loop again.*/
49 |       if (switchcount == 0 && dir == "asc") {
50 |         dir = "desc";
51 |         switching = true;
52 |       }
53 |     }
54 |   }
55 | }
56 | // from https://www.w3schools.com/howto/howto_js_filter_table.asp
57 | function filterTable() {
58 |   // Declare variables
59 |   var input, filter, table, tr, td, i;
60 |   input = document.getElementById("filterNotes");
61 |   filter = input.value.toUpperCase();
62 |   table = document.getElementById("notelistTable");
63 |   tr = table.getElementsByTagName("tr");
64 | 
65 |   // Loop through all table rows, and hide those who don't match the search query
66 |   for (i = 0; i < tr.length; i++) {
67 |     td = tr[i].getElementsByTagName("td")[0];
68 |     if (td) {
69 |       if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
70 |         tr[i].style.display = "";
71 |       } else {
72 |         tr[i].style.display = "none";
73 |       }
74 |     }
75 |   }
76 | }
77 | 


--------------------------------------------------------------------------------
/js/notelist.min.js:
--------------------------------------------------------------------------------
1 | function sortTable(a){var j,k,b,e,h,g,f,c,d=0;j=document.getElementById("notelistTable");b=true;c="asc";while(b){b=false;k=j.getElementsByTagName("TR");for(e=1;e<(k.length-1);e++){f=false;h=k[e].getElementsByTagName("TD")[a];g=k[e+1].getElementsByTagName("TD")[a];if(c=="asc"){if(h.innerHTML.toLowerCase()>g.innerHTML.toLowerCase()){f=true;break}}else{if(c=="desc"){if(h.innerHTML.toLowerCase()-1){e[b].style.display=""}else{e[b].style.display="none"}}}};


--------------------------------------------------------------------------------
/js/script.js:
--------------------------------------------------------------------------------
 1 | function uploadContent(force) {
 2 | 
 3 |   force = force || false; //force needed to add password even though the text is not changed
 4 |   // If textarea value changes.
 5 |   if (content !== textarea.value || force) {
 6 |     var temp = textarea.value;
 7 |     var request = new XMLHttpRequest();
 8 |     var saved = false;
 9 |     request.open('POST', window.location.href, true);
10 |     request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
11 | 
12 |     request.onreadystatechange = function() {
13 |       //if (this.readyState !== 4 || this.status !== 200) {
14 |       //  saved = "error";
15 |       //} // for lastUpdated status
16 |       // the password page won't show correctly if the textarea is there and the session has timed out but
17 |       //   we can still search for text displayed in the form as it is in the responseText
18 |       if (this.responseText.search("Invalid password") !== -1) {
19 |         location.reload();
20 |       }
21 |       //if (this.responseText.search("saved") > 0) {
22 |       //  saved = true;
23 |       //}
24 |       //} // will give a true here is password is set on blank note as note gets deleted
25 |       //if (this.responseText.search("deleted") !== -1) {
26 |       //  saved = true;
27 |       //} // will give a true here is password is set on blank note as note gets deleted
28 |       if (typeof lastUpdated === "function" ) {
29 |         lastUpdated(this.responseText);
30 |       } // check if the lastupdated functions are loaded
31 |     };
32 | 
33 |     request.onload = function() {
34 |       if (request.readyState === 4) {
35 | 
36 |         // Request has ended, check again after 1 second.
37 |         content = temp;
38 |         setTimeout(uploadContent, 1500); //increased time from 1 to 1.5 seconds to offset header check
39 |       }
40 |     }
41 | 
42 |     request.onerror = function() {
43 |       //saved = "error"; // for lastUpdated status
44 |       // Try again after 1 second
45 |       setTimeout(uploadContent, 1000);
46 |     }
47 | 
48 |     // Send the request.
49 |     var requestToSend = 'text=' + encodeURIComponent(temp);
50 |     if (typeof passwordRequest_Add === "function") {
51 |       requestToSend = passwordRequest_Add(requestToSend);
52 |     } //check if the password functions are loaded
53 |     if (typeof passwordRequest_Remove === "function") {
54 |       requestToSend = passwordRequest_Remove(requestToSend);
55 |     } //check if the password functions are loaded
56 |     request.send(requestToSend);
57 | 
58 |     // Make the content available to print.
59 |     printable.removeChild(printable.firstChild);
60 |     printable.appendChild(document.createTextNode(temp));
61 | 
62 |     if (document.getElementById("contentWithLinks")) {
63 |       // used by the simple view
64 |       document.getElementById("contentWithLinks").innerHTML = linkify(document.getElementById("printable").innerHTML).replace(/\r\n|\r|\n/g, "
"); 65 | var objDiv = document.getElementById("contentWithLinks").scrollHeight; //scroll to bottom as text added there 66 | } 67 | 68 | } else { 69 | 70 | // Content has not changed, check again after 1 second. 71 | setTimeout(uploadContent, 1000); 72 | if (typeof lastSaved === "function") { 73 | lastSaved(); 74 | } //check if the lastupdated functions are loaded 75 | } 76 | } 77 | 78 | var textarea = document.getElementById('content'); 79 | var printable = document.getElementById('printable'); 80 | var content = textarea.value; 81 | 82 | // Make the content available to print. 83 | printable.appendChild(document.createTextNode(content)); 84 | 85 | // Enable TABs to indent. Based on https://stackoverflow.com/a/14166052/1391963 86 | textarea.onkeydown = function(e) { 87 | if (e.keyCode === 9 || e.which === 9) { 88 | e.preventDefault(); 89 | var s = this.selectionStart; 90 | this.value = this.value.substring(0, this.selectionStart) + '\t' + this.value.substring(this.selectionEnd); 91 | this.selectionEnd = s + 1; 92 | } 93 | } 94 | 95 | textarea.focus(); 96 | uploadContent(); 97 | -------------------------------------------------------------------------------- /js/script.min.js: -------------------------------------------------------------------------------- 1 | function uploadContent(f){f=f||false;if(content!==textarea.value||f){var b=textarea.value;var e=new XMLHttpRequest();var d=false;e.open("POST",window.location.href,true);e.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");e.onreadystatechange=function(){if(this.responseText.search("Invalid password")!==-1){location.reload()}if(typeof lastUpdated==="function"){lastUpdated(this.responseText)}};e.onload=function(){if(e.readyState===4){content=b;setTimeout(uploadContent,1500)}};e.onerror=function(){setTimeout(uploadContent,1000)};var c="text="+encodeURIComponent(b);if(typeof passwordRequest_Add==="function"){c=passwordRequest_Add(c)}if(typeof passwordRequest_Remove==="function"){c=passwordRequest_Remove(c)}e.send(c);printable.removeChild(printable.firstChild);printable.appendChild(document.createTextNode(b));if(document.getElementById("contentWithLinks")){document.getElementById("contentWithLinks").innerHTML=linkify(document.getElementById("printable").innerHTML).replace(/\r\n|\r|\n/g,"
");var a=document.getElementById("contentWithLinks").scrollHeight}}else{setTimeout(uploadContent,1000);if(typeof lastSaved==="function"){lastSaved()}}}var textarea=document.getElementById("content");var printable=document.getElementById("printable");var content=textarea.value;printable.appendChild(document.createTextNode(content));textarea.onkeydown=function(b){if(b.keyCode===9||b.which===9){b.preventDefault();var a=this.selectionStart;this.value=this.value.substring(0,this.selectionStart)+"\t"+this.value.substring(this.selectionEnd);this.selectionEnd=a+1}};textarea.focus();uploadContent(); -------------------------------------------------------------------------------- /js/simple.js: -------------------------------------------------------------------------------- 1 | var textareaAdd = document.getElementById('contentAdd'); // used by the simple view 2 | 3 | textareaAdd.onkeydown = function(e) { 4 | if (e.keyCode === 9 || e.which === 9) { 5 | e.preventDefault(); 6 | var s = this.selectionStart; 7 | this.value = this.value.substring(0, this.selectionStart) + '\t' + this.value.substring(this.selectionEnd); 8 | this.selectionEnd = s + 1; 9 | } 10 | if (e.keyCode === 13 || e.which === 13) { 11 | e.preventDefault(); 12 | document.getElementById("content").value += '\n' + textareaAdd.value; 13 | this.value = ''; 14 | } 15 | } 16 | 17 | textareaAdd.focus(); 18 | -------------------------------------------------------------------------------- /js/simple.min.js: -------------------------------------------------------------------------------- 1 | var textareaAdd=document.getElementById("contentAdd");textareaAdd.onkeydown=function(b){if(b.keyCode===9||b.which===9){b.preventDefault();var a=this.selectionStart;this.value=this.value.substring(0,this.selectionStart)+"\t"+this.value.substring(this.selectionEnd);this.selectionEnd=a+1}if(b.keyCode===13||b.which===13){b.preventDefault();document.getElementById("content").value+="\n"+textareaAdd.value;this.value=""}};textareaAdd.focus(); -------------------------------------------------------------------------------- /modules/common.php: -------------------------------------------------------------------------------- 1 | console.log( 'Debug Objects: " . date('H:i:s'). " " . $output . "' );".PHP_EOL; 39 | } 40 | 41 | function writeToLog($txt) 42 | { 43 | file_put_contents('log.txt', date('Y-m-d H:i:s'). "\t" .$txt.PHP_EOL, FILE_APPEND | LOCK_EX); 44 | } 45 | -------------------------------------------------------------------------------- /modules/copy.php: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /modules/create_notes_folder.php: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /modules/css/lastsaved.css: -------------------------------------------------------------------------------- 1 | .savedStatus { 2 | /* bottomRightCorner */ 3 | font-size: 100%; 4 | font-family: monospace; 5 | position: absolute; 6 | bottom: 1px; 7 | right: 20px; 8 | } 9 | 10 | @media print { 11 | .savedStatus { 12 | display: none; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /modules/css/lastsaved.min.css: -------------------------------------------------------------------------------- 1 | .savedStatus{font-size:100%;font-family:monospace;position:absolute;bottom:1px;right:20px}@media print{.savedStatus{display:none}} -------------------------------------------------------------------------------- /modules/css/menu.css: -------------------------------------------------------------------------------- 1 | .wordwrap { 2 | /* used for the view functionality */ 3 | white-space: pre-wrap; 4 | /* CSS3 */ 5 | white-space: -moz-pre-wrap; 6 | /* Firefox */ 7 | white-space: -pre-wrap; 8 | /* Opera <7 */ 9 | white-space: -o-pre-wrap; 10 | /* Opera 7 */ 11 | word-wrap: break-word; 12 | /* IE */ 13 | } 14 | 15 | .footer { 16 | font-size: 100%; 17 | font-family: monospace; 18 | position: absolute; 19 | bottom: 0; 20 | left: 20px; 21 | text-align: left; 22 | } 23 | 24 | @media print { 25 | .footer { 26 | display: none; 27 | } 28 | } 29 | 30 | /* navbar css - https://www.w3schools.com/howto/howto_js_bottom_nav_responsive.asp */ 31 | .navbar { 32 | overflow: hidden; 33 | position: fixed; 34 | bottom: 0; 35 | min-width: 100px; 36 | background-color: #ebeef1; 37 | } 38 | 39 | .navbar a { 40 | float: left; 41 | display: block; 42 | color: black; 43 | text-align: center; 44 | padding: 1px 5px; 45 | text-decoration: underline; 46 | } 47 | 48 | .navbar a:hover { 49 | /*background-color: #ddd;*/ 50 | color: black; 51 | } 52 | 53 | .navbar a.active { 54 | color: black; 55 | } 56 | 57 | .navbar .icon { 58 | display: none; 59 | } 60 | 61 | @media screen and (max-width: 600px) { 62 | .navbar a:not(:nth-child(2)) { 63 | display: none; 64 | } 65 | 66 | .navbar a { 67 | font-size: 17px; 68 | } 69 | 70 | .navbar a.icon { 71 | position: relative; 72 | left: 0; 73 | bottom: 0; 74 | /*float: left;*/ 75 | display: block; 76 | } 77 | } 78 | 79 | @media screen and (max-width: 600px) { 80 | .navbar.responsive .icon { 81 | position: absolute; 82 | left: 0; 83 | bottom: 0; 84 | } 85 | 86 | .navbar.responsive a:not(:first-child) { 87 | float: none; 88 | display: block; 89 | text-align: left; 90 | margin-left: 40px !important; 91 | margin: 20px; 92 | } 93 | } 94 | 95 | /* end of navbar */ 96 | /* overlay from https://raventools.com/blog/create-a-modal-dialog-using-css-and-javascript/ */ 97 | #overlay { 98 | visibility: hidden; 99 | position: absolute; 100 | left: 0px; 101 | top: 0px; 102 | width: 100%; 103 | height: 100%; 104 | text-align: center; 105 | z-index: 1000; 106 | font-family: sans-serif; 107 | font-size: medium; 108 | } 109 | 110 | #overlay div { 111 | width: 250px; 112 | margin: 100px auto; 113 | background-color: #fff; 114 | border: 1px solid grey; 115 | padding: 15px; 116 | text-align: center; 117 | } 118 | 119 | body { 120 | height: 100%; 121 | margin: 0; 122 | padding: 0; 123 | } 124 | -------------------------------------------------------------------------------- /modules/css/menu.min.css: -------------------------------------------------------------------------------- 1 | .wordwrap{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}.footer{font-size:100%;font-family:monospace;position:absolute;bottom:0;left:20px;text-align:left}@media print{.footer{display:none}}.navbar{overflow:hidden;position:fixed;bottom:0;min-width:100px;background-color:#ebeef1}.navbar a{float:left;display:block;color:black;text-align:center;padding:1px 5px;text-decoration:underline}.navbar a:hover{color:black}.navbar a.active{color:black}.navbar .icon{display:none}@media screen and (max-width:600px){.navbar a:not(:nth-child(2)){display:none}.navbar a{font-size:17px}.navbar a.icon{position:relative;left:0;bottom:0;display:block}}@media screen and (max-width:600px){.navbar.responsive .icon{position:absolute;left:0;bottom:0}.navbar.responsive a:not(:first-child){float:none;display:block;text-align:left;margin-left:40px!important;margin:20px}}#overlay{visibility:hidden;position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:1000;font-family:sans-serif;font-size:medium}#overlay div{width:250px;margin:100px auto;background-color:#fff;border:1px solid grey;padding:15px;text-align:center}body{height:100%;margin:0;padding:0} -------------------------------------------------------------------------------- /modules/css/modal.css: -------------------------------------------------------------------------------- 1 | .modal_password, .modal_copy { 2 | position: fixed; 3 | left: 0; 4 | top: 0; 5 | width: 100%; 6 | height: 100%; 7 | background-color: rgba(0, 0, 0, 0.5); 8 | opacity: 0; 9 | visibility: hidden; 10 | transform: scale(1.1); 11 | } 12 | 13 | .modal-content { 14 | font-family: sans-serif; 15 | position: absolute; 16 | top: 50%; 17 | left: 50%; 18 | transform: translate(-50%, -50%); 19 | background-color: white; 20 | padding: 1rem 3rem; 21 | /*width: 24rem; */ 22 | border-radius: 0.5rem; 23 | } 24 | 25 | @media screen and (max-width: 600px) { 26 | .modal-content { 27 | width: 90%; 28 | padding: 1rem 1rem; 29 | } 30 | } 31 | 32 | .close-button_password, .close-button_copy { 33 | float: right; 34 | width: 1.5rem; 35 | line-height: 1.5rem; 36 | text-align: center; 37 | cursor: pointer; 38 | border-radius: 0.25rem; 39 | /* background-color: lightgray; */ 40 | } 41 | 42 | .show-modal { 43 | opacity: 1; 44 | visibility: visible; 45 | transform: scale(1.0); 46 | } 47 | 48 | .input, 49 | .submit { 50 | display: inline-block; 51 | padding: 10px 15px; 52 | margin-top: 10px; 53 | font-size: 10px; 54 | border-radius: 0; 55 | -webkit-appearance: none; 56 | } 57 | 58 | /* https://martinwolf.org/before-2018/blog/2015/07/equal-height-input-and-submit-button/ */ 59 | .input { 60 | border: 1px solid lightgray; 61 | } 62 | 63 | #allowReadOnlyView { 64 | margin-left:0; 65 | margin-top: 5px; 66 | } 67 | 68 | .submit { 69 | color: #fff; 70 | background-color: #337ab7; 71 | border-color: #2e6da4;; 72 | /** 73 | * If the input field has a border, 74 | * you need it here too to achieve equal heights. 75 | */ 76 | border: 1px solid transparent; 77 | } 78 | 79 | /* Firefox Fix - * Without that the submit button will be too high. */ 80 | .submit::-moz-focus-inner { 81 | border: 0; 82 | } 83 | -------------------------------------------------------------------------------- /modules/css/modal.min.css: -------------------------------------------------------------------------------- 1 | .modal_password,.modal_copy{position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.5);opacity:0;visibility:hidden;transform:scale(1.1)}.modal-content{font-family:sans-serif;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background-color:white;padding:1rem 3rem;border-radius:.5rem}@media screen and (max-width:600px){.modal-content{width:90%;padding:1rem 1rem}}.close-button_password,.close-button_copy{float:right;width:1.5rem;line-height:1.5rem;text-align:center;cursor:pointer;border-radius:.25rem}.show-modal{opacity:1;visibility:visible;transform:scale(1.0)}.input,.submit{display:inline-block;padding:10px 15px;margin-top:10px;font-size:10px;border-radius:0;-webkit-appearance:none}.input{border:1px solid lightgray}#allowReadOnlyView{margin-left:0;margin-top:5px}.submit{color:#fff;background-color:#337ab7;border-color:#2e6da4;border:1px solid transparent}.submit::-moz-focus-inner{border:0} -------------------------------------------------------------------------------- /modules/header.php: -------------------------------------------------------------------------------- 1 | if (typeof showRemovePassword === 'function') {showRemovePassword();}".PHP_EOL; // showRemovePassword if defined (in modal.js) 41 | if ($allowReadOnlyView == '1') { 42 | echo "".PHP_EOL; 43 | } // check allowReadOnlyView if set in the header 44 | } 45 | 46 | if (!isset($_SESSION)) { 47 | session_start(); 48 | } 49 | 50 | if ($allowReadOnlyView == '1' and basename($_SERVER['PHP_SELF']) == 'view.php') { /* viewing the page in readonly is ok from the view.php is ok so don't prompt for password */ 51 | } else { 52 | // if readonly view is not allowed and the calling page is not view.php then prompt for the password 53 | require_once 'modules/protect.php'; 54 | Protect\with('modules/protect_form.php', '', $passwordhash, $allowReadOnlyView); 55 | } 56 | } 57 | } 58 | return $headerFound; 59 | } 60 | 61 | function setHeader($allow_password) 62 | { 63 | // Add header data to the first line of the file - this will not be shown on the note 64 | if (!empty($_POST['notepwd'])) { 65 | $passwordhash = password_hash($_POST['notepwd'], PASSWORD_DEFAULT); 66 | } else { 67 | $passwordhash = ''; 68 | } 69 | if (!empty($_POST['allowReadOnlyView'])) { 70 | $allowReadOnlyView = $_POST['allowReadOnlyView']; 71 | } else { 72 | $allowReadOnlyView = 0; 73 | } 74 | $scope = current_url(); 75 | $session_key = 'password_protect_'.preg_replace('/\W+/', '_', $scope); 76 | if (!isset($_SESSION)) { 77 | session_start(); 78 | } 79 | // if the password and allowReadOnlyView hasn't been set from the form fields then get it from the session values 80 | // this solves the issue of not having the password on the page after it has been set 81 | if (isset($_SESSION[$session_key])) { 82 | if ($passwordhash == '' && $_SESSION[$session_key]) { 83 | $passwordhash=$_SESSION[$session_key.'hash']; 84 | } 85 | if (!empty($_POST['allowReadOnlyView']) == '' && $_SESSION[$session_key]) { 86 | $allowReadOnlyView=$_SESSION[$session_key.'allowReadOnlyView']; 87 | } 88 | } 89 | $noteHash = base64_encode($_GET['note']); // could also use rtrim(strtr(base64_encode($_GET['note']), '+/', '-_'), '='); to remove the = chars used for padding 90 | $header = "[header] " . "¬eName=" . $_GET['note'] . "¬eHash=" . $noteHash; // create the basic header content, really just an identifier 91 | $pwd = ""; 92 | if ($allow_password) { 93 | $pwd = "&password=" . $passwordhash; //. "&pwd=" . (isset($_POST['notepwd']) ? $_POST['notepwd'] : ''); 94 | $_SESSION[$session_key] = true; 95 | $_SESSION[$session_key.'hash'] = $passwordhash; 96 | // logic for allowing readonly view of note without password 97 | $pwd = $pwd . "&allowReadOnlyView=" . $allowReadOnlyView; 98 | $_SESSION[$session_key.'allowReadOnlyView'] = $allowReadOnlyView; 99 | // TODO: if the page is simple then rely on session setting 100 | } // create the password string for the header 101 | if (!empty($_POST['removePassword'])) { 102 | if ($_POST['removePassword'] == "1") { 103 | $pwd=""; 104 | unset($_SESSION[$session_key]); 105 | unset($_SESSION[$session_key.'hash']); 106 | unset($_SESSION[$session_key.'allowReadOnlyView']); 107 | } //remove the password 108 | } 109 | $header = $header . $pwd . "\n"; //add the password string to the header 110 | // check if anything has been added to the header (password or other) 111 | if (trim($header) == $header) { 112 | // if nothing has been added then no header is needed so set it to empty 113 | $header = ""; 114 | } 115 | return ($header); 116 | } 117 | 118 | function stripFirstLine($text) 119 | { 120 | // from http://stackoverflow.com/questions/7740405/php-delete-the-first-line-of-a-text-and-return-the-rest 121 | return substr($text, strpos($text, "\n")+1); //using \n instead of PHP_EOL as better compatibility moving files between Linux and Windows 122 | } 123 | -------------------------------------------------------------------------------- /modules/js/copy.js: -------------------------------------------------------------------------------- 1 | function copyToClipboard(elementId) { 2 | //https://jsfiddle.net/alvaroAV/a2pt16yq/ 3 | 4 | // Create an auxiliary hidden input 5 | var aux = document.createElement("textarea"); 6 | 7 | // Get the text from the element passed into the input 8 | if (elementId == 'copyURL') { 9 | aux.value = window.location.href; //get the url not the content 10 | } 11 | else if (elementId == 'copyURLViewOnly') { 12 | aux.value = window.location.href + '?view'; //get the view only url not the content 13 | } 14 | else { 15 | aux.value = document.getElementById(elementId).innerHTML; 16 | } 17 | 18 | // Append the aux input to the body 19 | document.body.appendChild(aux); 20 | 21 | // Highlight the content 22 | aux.select(); 23 | 24 | // Execute the copy command 25 | document.execCommand("copy"); 26 | 27 | // Remove the input from the body 28 | document.body.removeChild(aux); 29 | 30 | document.getElementById("copyMessage").innerHTML = "
Copied"; 31 | } 32 | -------------------------------------------------------------------------------- /modules/js/copy.min.js: -------------------------------------------------------------------------------- 1 | function copyToClipboard(b){var a=document.createElement("textarea");if(b=="copyURL"){a.value=window.location.href}else{if(b=="copyURLViewOnly"){a.value=window.location.href+"?view"}else{a.value=document.getElementById(b).innerHTML}}document.body.appendChild(a);a.select();document.execCommand("copy");document.body.removeChild(a);document.getElementById("copyMessage").innerHTML="
Copied"}; -------------------------------------------------------------------------------- /modules/js/lastsaved.js: -------------------------------------------------------------------------------- 1 | function lastUpdated(responseText) { 2 | // called when a note is saved 3 | var now = new Date(); 4 | var saved = ''; 5 | saved += ('0' + now.getHours()).slice(-2) + ':' + ('0' + now.getMinutes()).slice(-2) + ':' + ('0' + now.getSeconds()).slice(-2); 6 | var selector = document.getElementById('savedStatus'); 7 | selector.setAttribute('datetime', now.getTime()); 8 | //update the status so the user can see it has been saved 9 | document.getElementById("savedStatus").innerHTML = lastText() + saved; 10 | if (responseText.search("error") !== -1 && responseText.search("saved") > 0) { 11 | selector.setAttribute('datetime', ''); 12 | document.getElementById("savedStatus").innerHTML = responseText; 13 | } 14 | } 15 | 16 | function lastSaved() { 17 | // Update how long ago it was saved (comment out next 2 lines if do not want a status that is dynamic (showing how long ago it was last saved) 18 | // this will fire if there is no change to the file - basically just a clock 19 | var lastSave = document.getElementById('savedStatus').getAttribute("datetime"); 20 | if (lastSave) { 21 | var result = lastSave; 22 | if (isNaN(lastSave)) { 23 | var myDate = new Date(lastSave); 24 | result = myDate.getTime(); 25 | } 26 | var savedStatus = lastText() + ago(result) + ' ago'; 27 | //update the saved status if it has changed 28 | if (savedStatus != document.getElementById("savedStatus").innerHTML) document.getElementById("savedStatus").innerHTML = savedStatus; 29 | } 30 | } 31 | 32 | function lastText() { 33 | var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); 34 | var lastSavedText = "Last saved: "; 35 | if (w < 600) { 36 | lastSavedText = "Saved: "; 37 | } 38 | return lastSavedText; 39 | } 40 | -------------------------------------------------------------------------------- /modules/js/lastsaved.min.js: -------------------------------------------------------------------------------- 1 | function lastUpdated(d){var b=new Date();var c="";c+=("0"+b.getHours()).slice(-2)+":"+("0"+b.getMinutes()).slice(-2)+":"+("0"+b.getSeconds()).slice(-2);var a=document.getElementById("savedStatus");a.setAttribute("datetime",b.getTime());document.getElementById("savedStatus").innerHTML=lastText()+c;if(d.search("error")!==-1&&d.search("saved")>0){a.setAttribute("datetime","");document.getElementById("savedStatus").innerHTML=d}}function lastSaved(){var c=document.getElementById("savedStatus").getAttribute("datetime");if(c){var a=c;if(isNaN(c)){var b=new Date(c);a=b.getTime()}var d=lastText()+ago(a)+" ago";if(d!=document.getElementById("savedStatus").innerHTML){document.getElementById("savedStatus").innerHTML=d}}}function lastText(){var a=Math.max(document.documentElement.clientWidth,window.innerWidth||0);var b="Last saved: ";if(a<600){b="Saved: "}return b}; -------------------------------------------------------------------------------- /modules/js/menu.js: -------------------------------------------------------------------------------- 1 | // based on https://www.w3schools.com/howto/howto_js_bottom_nav_responsive.asp 2 | function navbarResponsive() { 3 | var x = document.getElementById("navbar"); 4 | if (x.className === "navbar") { 5 | x.className += " responsive"; 6 | } else { 7 | x.className = "navbar"; 8 | } 9 | } 10 | 11 | var menuButton = document.getElementById("menuButton"); 12 | 13 | function windowOnClick_navbar(event) { 14 | // hide responsive menu if displayed by clicking outside of it 15 | if (event.target.id !== "menuButton") { 16 | var el = document.getElementById('navbar'); 17 | if (el.className.indexOf('responsive') > -1) { 18 | el.className = 'navbar'; 19 | } 20 | } 21 | } 22 | 23 | window.addEventListener("click", windowOnClick_navbar); 24 | 25 | function downloadFile() { 26 | var link = document.createElement("a"); 27 | var content = document.getElementById('content').value; 28 | link.href = "data:application/txt," + encodeURIComponent(content) 29 | link.download = "note_" + document.title + ".txt"; 30 | link.dispatchEvent(new MouseEvent('click', { 31 | bubbles: true, 32 | cancelable: true, 33 | view: window 34 | })); 35 | // a [save as] dialog will be shown 36 | //window.open("data:application/txt," + encodeURIComponent(content), "_self"); 37 | } 38 | 39 | function toggleMonospace(lnk_obj) { 40 | var x = document.getElementById("content"); 41 | lnk_obj.innerHTML = (lnk_obj.innerHTML == '放大字体') ? '缩小字体' : '放大字体'; 42 | if (x.style.fontFamily == "monospace") { 43 | x.style.fontFamily = "sans-serif"; 44 | } else { 45 | x.style.fontFamily = "monospace"; 46 | } 47 | } 48 | 49 | function deleteFile() { 50 | var r = confirm("你确定要删除这个便签吗?"); 51 | if (r == true) { 52 | document.getElementById('content').value = ''; 53 | uploadContent(); 54 | alert('便签已删除'); 55 | // Note has been deleted so open a new note (going back to the same note, not a new note, looks confusing) 56 | var url = window.location.href; 57 | window.location.href = url.substring(0, url.lastIndexOf('/')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /modules/js/menu.min.js: -------------------------------------------------------------------------------- 1 | // based on https://www.w3schools.com/howto/howto_js_bottom_nav_responsive.asp 2 | function navbarResponsive() { 3 | var x = document.getElementById("navbar"); 4 | if (x.className === "navbar") { 5 | x.className += " responsive"; 6 | } else { 7 | x.className = "navbar"; 8 | } 9 | } 10 | 11 | var menuButton = document.getElementById("menuButton"); 12 | 13 | function windowOnClick_navbar(event) { 14 | // hide responsive menu if displayed by clicking outside of it 15 | if (event.target.id !== "menuButton") { 16 | var el = document.getElementById('navbar'); 17 | if (el.className.indexOf('responsive') > -1) { 18 | el.className = 'navbar'; 19 | } 20 | } 21 | } 22 | 23 | window.addEventListener("click", windowOnClick_navbar); 24 | 25 | function downloadFile() { 26 | var link = document.createElement("a"); 27 | var content = document.getElementById('content').value; 28 | link.href = "data:application/txt," + encodeURIComponent(content) 29 | link.download = "note_" + document.title + ".txt"; 30 | link.dispatchEvent(new MouseEvent('click', { 31 | bubbles: true, 32 | cancelable: true, 33 | view: window 34 | })); 35 | // a [save as] dialog will be shown 36 | //window.open("data:application/txt," + encodeURIComponent(content), "_self"); 37 | } 38 | 39 | function toggleMonospace(lnk_obj) { 40 | var x = document.getElementById("content"); 41 | lnk_obj.innerHTML = (lnk_obj.innerHTML == '放大字体') ? '缩小字体' : '放大字体'; 42 | if (x.style.fontFamily == "monospace") { 43 | x.style.fontFamily = "sans-serif"; 44 | } else { 45 | x.style.fontFamily = "monospace"; 46 | } 47 | } 48 | 49 | function deleteFile() { 50 | var r = confirm("你确定要删除这个便签吗?"); 51 | if (r == true) { 52 | document.getElementById('content').value = ''; 53 | uploadContent(); 54 | alert('便签已删除'); 55 | // Note has been deleted so open a new note (going back to the same note, not a new note, looks confusing) 56 | var url = window.location.href; 57 | window.location.href = url.substring(0, url.lastIndexOf('/')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /modules/js/modal.js: -------------------------------------------------------------------------------- 1 | //make sure the querySelector code is run *after* the page content loads 2 | // based on https://sabe.io/tutorials/how-to-create-modal-popup-box 3 | var modal_password = document.querySelector(".modal_password"); 4 | var modal_copy = document.querySelector(".modal_copy"); 5 | var closeButton_password = document.querySelector(".close-button_password"); 6 | var closeButton_copy = document.querySelector(".close-button_copy"); 7 | 8 | function toggleModal_Password() { 9 | //todo: add parameter for which modal to just a single function? 10 | inputboxLocation.innerHTML = "" 11 | modal_password.classList.toggle("show-modal"); 12 | document.getElementById("notepwd").focus(); 13 | } 14 | 15 | function toggleModal_Copy() { 16 | //todo: add parameter for which modal? 17 | document.getElementById("copyMessage").innerHTML = "

"; 18 | modal_copy.classList.toggle("show-modal"); 19 | } 20 | 21 | function windowOnClick_Modal(event) { 22 | // modal window windows if clicking outside of them 23 | if (event.target === modal_password) { 24 | toggleModal_Password(); 25 | } 26 | if (event.target === modal_copy) { 27 | toggleModal_Copy(); 28 | } 29 | } 30 | 31 | if (closeButton_password) closeButton_password.addEventListener("click", toggleModal_Password); 32 | if (closeButton_copy) closeButton_copy.addEventListener("click", toggleModal_Copy); 33 | window.addEventListener("click", windowOnClick_Modal); 34 | 35 | function showRemovePassword() { 36 | el = document.getElementById("removePassword"); 37 | el.style.display = (el.style.display == "none") ? "inline" : "none"; 38 | } 39 | 40 | function checkallowReadOnlyView() { 41 | el = document.getElementById('allowReadOnlyView'); 42 | el.checked = true; 43 | } 44 | 45 | function removePassword() { 46 | inputboxLocation.innerHTML = "" 47 | el = document.getElementById("overlay"); 48 | el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible"; 49 | document.getElementById("notepwd").focus(); 50 | } 51 | 52 | function isValid(str) { 53 | return str.replace(/^\s+/g, '').length; // boolean ('true' if field is empty) 54 | } 55 | -------------------------------------------------------------------------------- /modules/js/modal.min.js: -------------------------------------------------------------------------------- 1 | var modal_password=document.querySelector(".modal_password");var modal_copy=document.querySelector(".modal_copy");var closeButton_password=document.querySelector(".close-button_password");var closeButton_copy=document.querySelector(".close-button_copy");function toggleModal_Password(){inputboxLocation.innerHTML="";modal_password.classList.toggle("show-modal");document.getElementById("notepwd").focus()}function toggleModal_Copy(){document.getElementById("copyMessage").innerHTML="

";modal_copy.classList.toggle("show-modal")}function windowOnClick_Modal(a){if(a.target===modal_password){toggleModal_Password()}if(a.target===modal_copy){toggleModal_Copy()}}if(closeButton_password){closeButton_password.addEventListener("click",toggleModal_Password)}if(closeButton_copy){closeButton_copy.addEventListener("click",toggleModal_Copy)}window.addEventListener("click",windowOnClick_Modal);function showRemovePassword(){el=document.getElementById("removePassword");el.style.display=(el.style.display=="none")?"inline":"none"}function checkallowReadOnlyView(){el=document.getElementById("allowReadOnlyView");el.checked=true}function removePassword(){inputboxLocation.innerHTML="";el=document.getElementById("overlay");el.style.visibility=(el.style.visibility=="visible")?"hidden":"visible";document.getElementById("notepwd").focus()}function isValid(a){return a.replace(/^\s+/g,"").length}; -------------------------------------------------------------------------------- /modules/js/password.js: -------------------------------------------------------------------------------- 1 | function passwordRequest_Add(requestToSend) { 2 | var notepwd = (document.getElementById("notepwd")) ? document.getElementById("notepwd").value : ''; 3 | if (!isEmpty(notepwd)) { 4 | requestToSend = requestToSend + '¬epwd=' + encodeURIComponent(notepwd); 5 | } 6 | if ( document.getElementById("allowReadOnlyView").checked ) { 7 | requestToSend = requestToSend + '&allowReadOnlyView=1'; 8 | } 9 | return requestToSend; 10 | } 11 | 12 | function passwordRequest_Remove(requestToSend) { 13 | var removePassword = (document.getElementById("hdnRemovePassword")) ? document.getElementById("hdnRemovePassword").value : ''; 14 | if (!isEmpty(removePassword)) { 15 | requestToSend = requestToSend + '&removePassword=' + encodeURIComponent(removePassword); 16 | } 17 | return requestToSend; 18 | } 19 | 20 | function metadataGet(requestToSend) { 21 | if (!isEmpty(notepwd)) { 22 | requestToSend = requestToSend + '&metadataGet=1'; 23 | } 24 | return requestToSend; 25 | } 26 | 27 | function isEmpty(value) { 28 | return (value == null || value.length === 0); 29 | } 30 | 31 | function passwordRemove() { 32 | document.getElementById("hdnRemovePassword").value = "1"; 33 | uploadContent(true); 34 | toggleModal_Password(); 35 | document.getElementById("hdnRemovePassword").value = ""; 36 | showRemovePassword(); 37 | } 38 | 39 | function submitPassword() { 40 | if (isValid(notepwd.value)) { 41 | uploadContent(true); 42 | pwdMessage.innerHTML = ""; 43 | showRemovePassword(); 44 | toggleModal_Password(); 45 | } else { 46 | pwdMessage.innerHTML = "Please enter a password
"; 47 | } 48 | } 49 | 50 | // https://www.w3schools.com/howto/howto_js_trigger_button_enter.asp 51 | var passwordInput = document.getElementById("notepwd"); 52 | // Execute a function when the user releases a key on the keyboard 53 | if (passwordInput) { 54 | passwordInput.addEventListener("keyup", function(event) { 55 | event.preventDefault(); // Cancel the default action, if needed 56 | if (event.keyCode === 13) { // Number 13 is the "Enter" key on the keyboard 57 | document.getElementById("submitpwd").click(); // Trigger the button element with a click 58 | } 59 | }); } 60 | -------------------------------------------------------------------------------- /modules/js/password.min.js: -------------------------------------------------------------------------------- 1 | function passwordRequest_Add(a){var b=(document.getElementById("notepwd"))?document.getElementById("notepwd").value:"";if(!isEmpty(b)){a=a+"¬epwd="+encodeURIComponent(b)}if(document.getElementById("allowReadOnlyView").checked){a=a+"&allowReadOnlyView=1"}return a}function passwordRequest_Remove(b){var a=(document.getElementById("hdnRemovePassword"))?document.getElementById("hdnRemovePassword").value:"";if(!isEmpty(a)){b=b+"&removePassword="+encodeURIComponent(a)}return b}function metadataGet(a){if(!isEmpty(notepwd)){a=a+"&metadataGet=1"}return a}function isEmpty(a){return(a==null||a.length===0)}function passwordRemove(){document.getElementById("hdnRemovePassword").value="1";uploadContent(true);toggleModal_Password();document.getElementById("hdnRemovePassword").value="";showRemovePassword()}function submitPassword(){if(isValid(notepwd.value)){uploadContent(true);pwdMessage.innerHTML="";showRemovePassword();toggleModal_Password()}else{pwdMessage.innerHTML="Please enter a password
"}}var passwordInput=document.getElementById("notepwd");if(passwordInput){passwordInput.addEventListener("keyup",function(a){a.preventDefault();if(a.keyCode===13){document.getElementById("submitpwd").click()}})}; -------------------------------------------------------------------------------- /modules/js/tinyago.js: -------------------------------------------------------------------------------- 1 | function ago(val) { 2 | // https://github.com/odyniec/tinyAgo-js 3 | // val is datetime in milliseconds 4 | val = 0 | (Date.now() - val) / 1000; 5 | var unit, length = { 6 | second: 60, 7 | minute: 60, 8 | hour: 24, 9 | day: 7, 10 | week: 4.35, 11 | month: 12, 12 | year: 10000 13 | }, 14 | result; 15 | 16 | for (unit in length) { 17 | result = val % length[unit]; 18 | if (!(val = 0 | val / length[unit])) 19 | return result + ' ' + (result - 1 ? unit + 's' : unit); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /modules/js/tinyago.min.js: -------------------------------------------------------------------------------- 1 | function ago(d){d=0|(Date.now()-d)/1000;var c,b={second:60,minute:60,hour:24,day:7,week:4.35,month:12,year:10000},a;for(c in b){a=d%b[c];if(!(d=0|d/b[c])){return a+" "+(a-1?c+"s":c)}}}; -------------------------------------------------------------------------------- /modules/js/view.js: -------------------------------------------------------------------------------- 1 | function linkify(inputText) { 2 | // from https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links 3 | var replacedText, replacePattern1, replacePattern2, replacePattern3; 4 | 5 | //URLs starting with http://, https://, or ftp:// 6 | replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; 7 | replacedText = inputText.replace(replacePattern1, '$1'); 8 | 9 | //URLs starting with "www." (without // before it, or it'd re-link the ones done above). 10 | replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; 11 | replacedText = replacedText.replace(replacePattern2, '$1$2'); 12 | 13 | //Change email addresses to mailto:: links. 14 | replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim; 15 | replacedText = replacedText.replace(replacePattern3, '$1'); 16 | 17 | return replacedText; 18 | } 19 | 20 | function CreateViewable(noBorder) { 21 | var newNode = document.createElement("div"); // Create the new node to insert 22 | newNode.id = "contentWithLinks"; // give it an id attribute called 'newSpan' 23 | var referenceNode = document.getElementById("content"); // Get the reference node 24 | referenceNode.parentNode.insertBefore(newNode, referenceNode); // Insert the new node before the reference node 25 | document.getElementById("contentWithLinks").innerHTML = linkify(document.getElementById("printable").innerHTML).replace(/\r\n|\r|\n/g, "
"); 26 | 27 | //added for IE9 compatibility 28 | //https://www.w3schools.com/howto/howto_js_add_class.asp 29 | var element, name, arr; 30 | element = document.getElementById("contentWithLinks"); 31 | name = "content wordwrap"; 32 | arr = element.className.split(" "); 33 | if (arr.indexOf(name) == -1) { 34 | element.className += " " + name; 35 | } 36 | if (noBorder) element.style.border='none'; 37 | } 38 | 39 | function toggleView(lnk_obj) { 40 | var x = document.getElementById("content"); 41 | lnk_obj.innerHTML = (lnk_obj.innerHTML == 'view') ? 'edit' : 'view'; 42 | if (x.style.display === "none") { 43 | x.style.display = "block"; 44 | var element = document.getElementById("contentWithLinks"); 45 | element.parentNode.removeChild(element); 46 | } else { 47 | x.style.display = "none"; 48 | CreateViewable(); 49 | } 50 | } 51 | 52 | function viewOnly() { 53 | //no textarea available with the view option so show the links enabled view 54 | var x = document.getElementById("content"); 55 | x.style.display = "none"; 56 | CreateViewable(true); 57 | } 58 | 59 | // Go back to Edit (from View with links) by pressing the Esc key 60 | document.onkeydown = function(evt) { 61 | evt = evt || window.event; 62 | if (evt.keyCode == 27) { 63 | if (document.getElementById("password_modal").className == 'modal_password show-modal') { 64 | toggleModal_Password(); 65 | return; 66 | } 67 | if (document.getElementById("content").style.display == "none") { 68 | toggleView(document.getElementById("a_view")); 69 | } 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /modules/js/view.min.js: -------------------------------------------------------------------------------- 1 | function linkify(e) { 2 | var b, d, c, a; 3 | d = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; 4 | b = e.replace(d, '$1'); 5 | c = /(^|[^\/])(www\.[\S]+(\b|$))/gim; 6 | b = b.replace(c, '$1$2'); 7 | a = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim; 8 | b = b.replace(a, '$1'); 9 | return b; 10 | } 11 | function CreateViewable(f) { 12 | var e = document.createElement("div"); 13 | e.id = "contentWithLinks"; 14 | var b = document.getElementById("content"); 15 | b.parentNode.insertBefore(e, b); 16 | document.getElementById("contentWithLinks").innerHTML = linkify( 17 | document.getElementById("printable").innerHTML 18 | ).replace(/\r\n|\r|\n/g, "
"); 19 | var d, c, a; 20 | d = document.getElementById("contentWithLinks"); 21 | c = "content wordwrap"; 22 | a = d.className.split(" "); 23 | if (a.indexOf(c) == -1) { 24 | d.className += " " + c; 25 | } 26 | if (f) { 27 | d.style.border = "none"; 28 | } 29 | } 30 | function toggleView(b) { 31 | var a = document.getElementById("content"); 32 | b.innerHTML = b.innerHTML == "查看便签" ? "编辑便签" : "查看便签"; 33 | if (a.style.display === "none") { 34 | a.style.display = "block"; 35 | var c = document.getElementById("contentWithLinks"); 36 | c.parentNode.removeChild(c); 37 | } else { 38 | a.style.display = "none"; 39 | CreateViewable(); 40 | } 41 | } 42 | function viewOnly() { 43 | var a = document.getElementById("content"); 44 | a.style.display = "none"; 45 | CreateViewable(true); 46 | } 47 | document.onkeydown = function (a) { 48 | a = a || window.event; 49 | if (a.keyCode == 27) { 50 | if ( 51 | document.getElementById("password_modal").className == 52 | "modal_password show-modal" 53 | ) { 54 | toggleModal_Password(); 55 | return; 56 | } 57 | if (document.getElementById("content").style.display == "none") { 58 | toggleView(document.getElementById("a_view")); 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /modules/lastsaved.php: -------------------------------------------------------------------------------- 1 | 2 |
">
5 | 6 | 7 | -------------------------------------------------------------------------------- /modules/menu.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 29 | 30 | ".PHP_EOL; ?> 31 | -------------------------------------------------------------------------------- /modules/password.php: -------------------------------------------------------------------------------- 1 | 2 | 16 | -------------------------------------------------------------------------------- /modules/protect.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 62 | <?php if (isset($_GET['note'])) print $_GET['note']; ?> 63 | 64 | 65 |
66 |
67 | 68 | 无效的密码 69 | 70 | 访问密码:
71 | 72 | 73 |

此便签有密码
创建一个新的便签

74 | 75 |

">只读模式查看

76 | 77 |
78 |
79 | 80 | 81 | -------------------------------------------------------------------------------- /nginx.conf.example: -------------------------------------------------------------------------------- 1 | # this is just an example of what is reuired in the nginx.conf file to support url rewrite 2 | # ensure the location matches the location minimal-web-notepad is served from 3 | # example based on solution from @eonegh - see https://github.com/domOrielton/minimal-web-notepad/issues/4 4 | 5 | location / { 6 | if ($query_string ~ "^view") { 7 | rewrite ^/([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)$ /view.php?note=$1 last; 8 | } 9 | if ($query_string ~ "^simple") { 10 | rewrite ^/([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)$ /simple.php?note=$1 last; 11 | } 12 | rewrite ^/([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)$ /index.php?note=$1 last; 13 | } 14 | add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; 15 | -------------------------------------------------------------------------------- /notelist.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | = $lengths[$j] && $j < count($lengths) - 1; $j++) { 27 | $difference /= $lengths[$j]; 28 | } 29 | 30 | $difference = round($difference); 31 | 32 | // if ($difference != 1) { 33 | // $periods[$j] .= "s"; 34 | // } 35 | 36 | return "$difference$periods[$j]$tense"; 37 | } 38 | 39 | function human_filesize($bytes, $decimals = 2) 40 | { 41 | // 来自用户在 phpfilesize 页面上的贡献 42 | $sz = 'bkMGTP'; 43 | $szWords = array('字节', 'KB', 'MB', 'GB', 'TB', 'PB'); 44 | $factor = floor((strlen($bytes) - 1) / 3); 45 | 46 | if (@$sz[$factor] == 'b') { 47 | $decimals = 0; 48 | } 49 | 50 | return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . '' . @$szWords[$factor]; 51 | } 52 | ?> 53 | 54 | 55 | 便签列表 56 | 57 | 58 | 108 | 109 | 110 | 新建便签

111 | 112 | 113 | 115 | 116 |
117 | 118 | 119 | 120 | 121 | 122 | $counterMax) { 129 | echo ""; 130 | break; // 有一个最大显示的便签数 131 | } 132 | 133 | echo ""; 134 | echo ""; 135 | echo ""; 136 | echo ""; 137 | 138 | $counter++; 139 | } 140 | ?> 141 |
名称最后修改时间文件大小
达到最大显示便签数(" . $counterMax . ")
" . $value . "" . ago(filemtime($data_directory . '/' . $value)) . "" . human_filesize(filesize($data_directory . '/' . $value)) . "
142 | 143 | 144 | -------------------------------------------------------------------------------- /passwordHelp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 便签 - 密码保护 8 | 18 | 19 | 20 | 21 | 关于便签密码保护的一些信息: 22 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /setup.php: -------------------------------------------------------------------------------- 1 | '; 13 | 14 | // make sure there is an .htaccess file there 15 | // if there is not then create one 16 | $file = $data_directory .'/.htaccess'; 17 | if (makehtaccess($file)) { echo '.htaccess file ok in the ' . $data_directory. ' data directory
'; } else { echo '.htaccess file exists in the ' . $data_directory .' data directory
'; } 18 | } else { 19 | echo $data_directory . ' folder does not exist and could not be created
'; 20 | } 21 | 22 | // based on https://raw.githubusercontent.com/bolt/htaccess_tester/master/htaccess_tester.php 23 | if (is_readable(__DIR__.'/.htaccess') ) { 24 | 25 | echo "

The .htaccess file exists in this folder and is readable to the webserver. These are its contents which should match the repos version:

\n
";
26 |     echo file_get_contents(__DIR__.'/.htaccess');
27 |     echo "
"; 28 | 29 | } else { 30 | 31 | echo "

Error: The .htaccess file does not exist in this folder or it is not readable to the webserver.

Ensure a .htaccess file is here and matches the repos version. Make sure it is readable to the webserver.

"; 32 | die(); 33 | 34 | } 35 | 36 | // https://stackoverflow.com/questions/109188/how-do-i-check-if-a-directory-is-writeable-in-php 37 | if ( ! is_writable(dirname($data_directory))) { 38 | echo dirname($data_directory) . ' must be writable! Please change the permissions to 0744 or 0755
'; 39 | } else { 40 | echo $data_directory . ' is writable
'; 41 | } 42 | 43 | 44 | // https://stackoverflow.com/questions/2303372/create-a-folder-if-it-doesnt-already-exist 45 | function makeDir($path) 46 | { 47 | return is_dir($path) || mkdir($path, 0744); 48 | } 49 | 50 | // https://stackoverflow.com/questions/20580017/php-create-a-file-if-not-exists 51 | function makehtaccess($file) 52 | { 53 | if(!is_file($file)){ 54 | $contents = 'Deny from all'; // deny all 55 | return file_put_contents($file, $contents); // save content to the file 56 | } 57 | } 58 | ?> 59 | -------------------------------------------------------------------------------- /simple.php: -------------------------------------------------------------------------------- 1 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | <?php print $_GET['note']; ?> 62 | 63 | 64 | 65 | 66 |
67 | 68 | 71 |
72 |

73 |     
74 |     
75 |     
76 |   	
82 |     
83 |     
84 | 
85 | 
86 | 


--------------------------------------------------------------------------------
/view.php:
--------------------------------------------------------------------------------
 1 | 
22 | 
23 | 
24 |     
25 |     
26 | 		
27 |     <?php print $_GET['note']; ?>
28 |     
29 |     
30 |     
31 | 
32 | 
33 |   
34 |
37 |
38 |
39 | 42 | 43 | 44 | --------------------------------------------------------------------------------