Initial commit
This commit is contained in:
commit
c42c3661d5
34
_htaccess
Normal file
34
_htaccess
Normal file
@ -0,0 +1,34 @@
|
||||
RewriteEngine on
|
||||
RewriteBase /textfiles/
|
||||
|
||||
# Send requests without parameters to textfiles.php.
|
||||
# RewriteRule ^$ textfiles.php [L]
|
||||
|
||||
# Send requests for index.php to textfiles.php.
|
||||
# RewriteRule ^index\.php$ textfiles.php [L]
|
||||
|
||||
# Send requests for index.html to textfiles.php.
|
||||
# RewriteRule ^index\.html$ textfiles.php [L]
|
||||
|
||||
# Send requests for textfiles.css to textfiles.css.
|
||||
RewriteRule ^textfiles\.css$ textfiles.css [L]
|
||||
|
||||
# Send requests for textfiles.js to textfiles.js.
|
||||
RewriteRule ^textfiles\.js$ textfiles.js [L]
|
||||
|
||||
# Send requests for textfiles.php to textfiles.php.
|
||||
RewriteRule ^textfiles\.php$ textfiles.php [L]
|
||||
|
||||
# Send requests for textfiles.html to textfiles.php.
|
||||
# NOTE: THIS IS NOT A TYPO!
|
||||
RewriteRule ^textfiles\.html$ textfiles.php [L]
|
||||
|
||||
# Send requests for files that exist to textfiles.php (raw).
|
||||
RewriteCond %{REQUEST_URI} ^\/textfiles\/(.+)/raw$
|
||||
RewriteCond /file/path/to/your/textfiles/%1 -f
|
||||
RewriteRule ^(.+)/raw$ textfiles.php?f=$1&m=raw [QSA,L]
|
||||
|
||||
# Send requests for files that exist to textfiles.php.
|
||||
RewriteCond %{REQUEST_URI} ^\/textfiles\/(.+)$
|
||||
RewriteCond /file/path/to/your/textfiles/%1 -f
|
||||
RewriteRule ^(.+)$ textfiles.php?f=$1 [QSA,L]
|
||||
153
textfiles.css
Normal file
153
textfiles.css
Normal file
@ -0,0 +1,153 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font-size: 20px;
|
||||
}
|
||||
*, *::before, *::after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.compensator {
|
||||
width: 15rem;
|
||||
height: 4.5rem;
|
||||
float: right;
|
||||
pointer-events: none;
|
||||
}
|
||||
@media only screen and (max-width: 520px) {
|
||||
.compensator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: Inconsolata, monospace;
|
||||
-moz-tab-size: 4;
|
||||
tab-size: 4;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: break-word;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#ui-elements-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
pointer-events: none;
|
||||
}
|
||||
#ui-elements-container > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#controls {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
@media only screen and (max-width: 520px) {
|
||||
#controls {
|
||||
display: flex;
|
||||
flex-flow: row-reverse;
|
||||
align-items: flex-end;
|
||||
width: 100%;
|
||||
top: unset;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
#controls .buttons {
|
||||
display: flex;
|
||||
flex-flow: row-reverse wrap;
|
||||
background-color: #fff;
|
||||
padding: 1px;
|
||||
}
|
||||
@media only screen and (max-width: 520px) {
|
||||
#controls .buttons {
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
|
||||
#controls .button {
|
||||
background-color: #e00;
|
||||
font-size: 1.5em;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 3.5rem;
|
||||
height: 3.5rem;
|
||||
text-decoration: none;
|
||||
font-family: Font Awesome;
|
||||
color: #fff;
|
||||
padding: 1px 0 0 0;
|
||||
border: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
#controls .button + .button {
|
||||
margin: 0 1px 0 0;
|
||||
}
|
||||
@media only screen and (max-width: 520px) {
|
||||
#controls .button + .button {
|
||||
margin: 1px 0 0 0;
|
||||
}
|
||||
}
|
||||
@media only screen and (hover:hover) and (pointer:fine) {
|
||||
#controls .button:hover {
|
||||
color: gold;
|
||||
}
|
||||
}
|
||||
#controls .button:active {
|
||||
transform: scale(0.975);
|
||||
}
|
||||
#controls .button:focus {
|
||||
outline: none;
|
||||
}
|
||||
#controls .button::after {
|
||||
content: attr(data-label);
|
||||
display: block;
|
||||
font-family: sans-serif;
|
||||
font-size: 0.5rem;
|
||||
font-weight: bold;
|
||||
margin: 6px 0 0 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#controls .message {
|
||||
display: block;
|
||||
margin: 1px 0 0 0;
|
||||
padding: 0.25em 0.5em;
|
||||
text-align: center;
|
||||
font-family: sans-serif;
|
||||
font-size: 0.75em;
|
||||
color: #b00;
|
||||
}
|
||||
#controls .message:not(:empty) {
|
||||
background-color: #fff;
|
||||
}
|
||||
@media only screen and (max-width: 520px) {
|
||||
#controls .message {
|
||||
margin: 0 0 1px 1px;
|
||||
flex: 1 1 100%;
|
||||
padding: 0.5em 0.75em;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
#controls .message:not(:empty) {
|
||||
outline: 1px solid #fff;
|
||||
border: 1px solid #e00;
|
||||
}
|
||||
}
|
||||
|
||||
#scratchpad {
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
}
|
||||
93
textfiles.html
Normal file
93
textfiles.html
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
$filename = $_GET['f'];
|
||||
$stylesheet = "textfiles.css";
|
||||
$stylesheet_href = $stylesheet . "?v=" . filemtime($stylesheet);
|
||||
|
||||
?>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href='https://your.web.site/FontAwesome.css' type='text/css' rel='stylesheet' />
|
||||
<link href='<?php echo $stylesheet_href; ?>' type='text/css' rel='stylesheet' />
|
||||
<script type='text/javascript' src='textfiles.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class='compensator'>
|
||||
</div>
|
||||
|
||||
<pre>
|
||||
<?php echo htmlentities(file_get_contents($filename)); ?>
|
||||
</pre>
|
||||
|
||||
<div id='ui-elements-container'>
|
||||
<div id='controls'>
|
||||
<div class='buttons'>
|
||||
<button
|
||||
type='button'
|
||||
class='button copy-raw-link'
|
||||
title='Copy raw link to clipboard [k]'
|
||||
data-label='Raw link'
|
||||
data-main-action='copyRawLinkButtonClicked'
|
||||
data-success-message='Raw file URL copied to clipboard.'
|
||||
accesskey='k'
|
||||
></button>
|
||||
<a
|
||||
class='button raw'
|
||||
title='View raw file [r]'
|
||||
data-label='View raw'
|
||||
accesskey='r'
|
||||
href='<?php echo str_replace('.txt', '', $filename); ?>/raw'
|
||||
></a>
|
||||
<button
|
||||
type='button'
|
||||
class='button copy-text'
|
||||
title='Copy text to clipboard [c]'
|
||||
data-label='Copy text'
|
||||
data-main-action='copyTextButtonClicked'
|
||||
data-success-message='Text copied to clipboard.'
|
||||
accesskey='c'
|
||||
></button>
|
||||
<button
|
||||
type='button'
|
||||
class='button copy-link'
|
||||
title='Copy link to clipboard [l]'
|
||||
data-label='Copy link'
|
||||
data-main-action='copyLinkButtonClicked'
|
||||
data-success-message='URL copied to clipboard.'
|
||||
accesskey='l'
|
||||
></button>
|
||||
</div>
|
||||
<span class='message'></span>
|
||||
</div>
|
||||
<textarea id='scratchpad'></textarea>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<script type='text/javascript'>
|
||||
copyLinkButtonClicked = () => {
|
||||
copyTextToClipboard(location);
|
||||
};
|
||||
copyRawLinkButtonClicked = () => {
|
||||
copyTextToClipboard(location + "/raw");
|
||||
};
|
||||
copyTextButtonClicked = () => {
|
||||
selectElementContents(document.querySelector("pre"));
|
||||
document.execCommand("copy");
|
||||
};
|
||||
|
||||
document.querySelectorAll("#controls button").forEach(button => {
|
||||
button.addActivateEvent((event) => {
|
||||
event.target.blur();
|
||||
window[event.target.dataset["mainAction"]]();
|
||||
setMessage(event.target.dataset["successMessage"]);
|
||||
});
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
selectElementContents(document.querySelector("pre"));
|
||||
}, 0);
|
||||
</script>
|
||||
</html>
|
||||
46
textfiles.js
Normal file
46
textfiles.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*******************************/
|
||||
/* EVENT LISTENER MANIPULATION */
|
||||
/*******************************/
|
||||
|
||||
/* Adds an event listener to a button (or other clickable element), attaching
|
||||
it to both "click" and "keyup" events (for use with keyboard navigation).
|
||||
Optionally also attaches the listener to the 'mousedown' event, making the
|
||||
element activate on mouse down instead of mouse up. */
|
||||
Element.prototype.addActivateEvent = function(func, includeMouseDown) {
|
||||
let ael = this.activateEventListener = (event) => { if (event.button === 0 || event.key === ' ') func(event) };
|
||||
if (includeMouseDown) this.addEventListener("mousedown", ael);
|
||||
this.addEventListener("click", ael);
|
||||
this.addEventListener("keyup", ael);
|
||||
}
|
||||
|
||||
/* Removes event listener from a clickable element, automatically detaching it
|
||||
from all relevant event types. */
|
||||
Element.prototype.removeActivateEvent = function() {
|
||||
let ael = this.activateEventListener;
|
||||
this.removeEventListener("mousedown", ael);
|
||||
this.removeEventListener("click", ael);
|
||||
this.removeEventListener("keyup", ael);
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* HELPERS */
|
||||
/***********/
|
||||
|
||||
function selectElementContents(element) {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(element);
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
function copyTextToClipboard(string) {
|
||||
let scratchpad = document.querySelector("#scratchpad");
|
||||
scratchpad.value = string;
|
||||
scratchpad.select();
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
function setMessage(string) {
|
||||
document.querySelector("#controls .message").innerText = string;
|
||||
}
|
||||
41
textfiles.php
Normal file
41
textfiles.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
$base_url = "https://your.web.site/textfiles/";
|
||||
|
||||
if (isset($_GET['f'])) {
|
||||
render_file();
|
||||
} else if ( isset($_POST['f'])
|
||||
&& isset($_POST['p'])
|
||||
&& $_POST['p'] == 'YOUR_API_KEY_GOES_HERE') {
|
||||
new_file();
|
||||
} else {
|
||||
header ('Content-type: text/plain; charset=utf-8');
|
||||
http_response_code(404);
|
||||
die("NO FILE FOR YOU!! COME BACK, ONE YEAR!");
|
||||
}
|
||||
|
||||
## Functions
|
||||
|
||||
function render_file() {
|
||||
if ($_GET['m'] == 'raw') {
|
||||
header ('Content-type: text/plain; charset=utf-8');
|
||||
echo file_get_contents($_GET['f']);
|
||||
die;
|
||||
} else {
|
||||
header ('Content-type: text/html; charset=utf-8');
|
||||
include_once(__DIR__ . "/textfiles.html");
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
function new_file() {
|
||||
`export LANG="en_US.UTF-8"`;
|
||||
$tmp_file_path = trim(`mktemp -q ./XXXXXXXX`);
|
||||
$tmp_file_name = `basename {$tmp_file_path}`;
|
||||
`rm {$tmp_file_path}`;
|
||||
file_put_contents("{$tmp_file_path}.txt", $_POST['f']);
|
||||
global $base_url;
|
||||
echo $base_url . $tmp_file_name;
|
||||
}
|
||||
|
||||
?>
|
||||
Loading…
Reference in New Issue
Block a user