Upload files to 'user'
129
user/CONTRIBUTING.md
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Please take a moment to review this document in order to make the contribution
|
||||||
|
process easy and effective for everyone involved.
|
||||||
|
|
||||||
|
Submitting an issue that is improperly or incompletely written is a waste of time for everybody.
|
||||||
|
|
||||||
|
Following these guidelines helps to communicate that you respect the time of
|
||||||
|
the developers managing and developing this open source project. In return,
|
||||||
|
they should reciprocate that respect in addressing your issue or assessing
|
||||||
|
patches and features.
|
||||||
|
|
||||||
|
|
||||||
|
## Using the issue tracker
|
||||||
|
|
||||||
|
The issue tracker is the preferred channel for [bug reports](#bug-reports),
|
||||||
|
[feature requests](#feature-requests) and [submitting pull
|
||||||
|
requests](#pull-requests), but please respect the following restrictions:
|
||||||
|
|
||||||
|
* Please **do not** use the issue tracker for personal support requests.
|
||||||
|
Use [discussions](https://github.com/telepathics/yourls-emojis/discussions) instead to ask the community for help.
|
||||||
|
|
||||||
|
* Please **do not** derail or troll issues.
|
||||||
|
Keep the discussion on topic and respect the opinions of others.
|
||||||
|
|
||||||
|
|
||||||
|
## Bug reports
|
||||||
|
|
||||||
|
A bug is a _demonstrable problem_ that is caused by the code in the repository.
|
||||||
|
Good bug reports are extremely helpful - thank you!
|
||||||
|
|
||||||
|
Guidelines for bug reports:
|
||||||
|
|
||||||
|
1. **Use the GitHub issue search**
|
||||||
|
Check if the issue has already been reported. Reporting duplicates is a waste of
|
||||||
|
time for everyone. Search in **all issues**, open and closed.
|
||||||
|
2. **Check if the issue has been fixed**
|
||||||
|
Try to reproduce it using the latest `master` or development branch in the repository.
|
||||||
|
Maybe it has been fixed since the last stable release.
|
||||||
|
3. **Give details**
|
||||||
|
A good bug report shouldn't leave others needing to chase you up for more
|
||||||
|
information. Please try to be as detailed as possible in your report.
|
||||||
|
Give any information that is relevant to the bug:
|
||||||
|
* YOURLS & MySQL & PHP versions
|
||||||
|
* Server Software
|
||||||
|
* Browser name & version
|
||||||
|
|
||||||
|
What is the expected output? What do you see instead? See the report example below.
|
||||||
|
7. **Isolate the problem**
|
||||||
|
Isolate the problem as much as you can, reduce to the bare minimum required to reproduce the issue.
|
||||||
|
Don't describe a general situation that doesn't work as expected and just count on us to pin
|
||||||
|
point the problem.
|
||||||
|
|
||||||
|
|
||||||
|
## Feature requests
|
||||||
|
|
||||||
|
Feature requests are welcome. But take a moment to find out whether your idea
|
||||||
|
fits with the scope and aims of the project. It's up to *you* to make a strong
|
||||||
|
case to convince the YOURLS developers of the merits of this feature. Please
|
||||||
|
provide as much detail and context as possible.
|
||||||
|
|
||||||
|
|
||||||
|
## Pull requests
|
||||||
|
|
||||||
|
Good pull requests - patches, improvements, new features - are a fantastic
|
||||||
|
help. They should remain focused in scope and avoid containing unrelated
|
||||||
|
commits.
|
||||||
|
|
||||||
|
1. **Please ask first**
|
||||||
|
Before embarking on any significant pull request (e.g. implementing features,
|
||||||
|
refactoring code), otherwise you risk spending a lot of time working on
|
||||||
|
something that the developers might not want to merge into the project.
|
||||||
|
2. **Licensing**
|
||||||
|
By submitting a patch, you agree that your code will be licensed under the
|
||||||
|
[MIT License](https://github.com/telepathics/yourls-emojis/blob/master/LICENSE) terms.
|
||||||
|
3. **Coding Standards**
|
||||||
|
Please adhere to the coding conventions used throughout the project (indentation,
|
||||||
|
comments, etc.). Make sure you've tested your patch under
|
||||||
|
different scenarios (various browsers, non default installation path, etc.).
|
||||||
|
|
||||||
|
Adhering to the following this process is the best way to get your work
|
||||||
|
merged:
|
||||||
|
|
||||||
|
1. [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo), clone your fork,
|
||||||
|
and configure the remotes.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone your fork of the repo into the current directory
|
||||||
|
git clone https://github.com/<your-username>/<repo-name>
|
||||||
|
# Navigate to the newly cloned directory
|
||||||
|
cd <repo-name>
|
||||||
|
# Assign the original repo to a remote called "upstream"
|
||||||
|
git remote add upstream https://github.com/<upsteam-owner>/<repo-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. If you cloned a while ago, get the latest changes from upstream.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout <dev-branch>
|
||||||
|
git pull upstream <dev-branch>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Create a new topic branch (off the main project development branch) to
|
||||||
|
contain your feature, change, or fix.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout -b <topic-branch-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Commit your changes in logical chunks. Please adhere to these [git commit
|
||||||
|
message guidelines](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
|
||||||
|
or your code is unlikely be merged into the main project. Use Git's
|
||||||
|
[interactive rebase](https://docs.github.com/en/github/using-git/about-git-rebase)
|
||||||
|
feature to tidy up your commits before making them public.
|
||||||
|
|
||||||
|
5. Locally merge (or rebase) the upstream development branch into your topic branch:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull [--rebase] upstream <dev-branch>
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Push your topic branch up to your fork:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git push origin <topic-branch-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
10. [Open a Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
|
||||||
|
with a clear title and description.
|
445
user/ClassLoader.php
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see http://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see http://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
// PSR-4
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
private $useIncludePath = false;
|
||||||
|
private $classMap = array();
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
private $missingClasses = array();
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $classMap Class to filename map
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param array|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param array|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param array|string $paths The PSR-0 base directories
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param array|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return bool|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*/
|
||||||
|
function includeFile($file)
|
||||||
|
{
|
||||||
|
include $file;
|
||||||
|
}
|
203
user/EmojiDetector.php
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SteppingHat\EmojiDetector;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use SteppingHat\EmojiDetector\Model\EmojiInfo;
|
||||||
|
|
||||||
|
class EmojiDetector {
|
||||||
|
|
||||||
|
const LONGEST_EMOJI = 8;
|
||||||
|
|
||||||
|
const SKIN_TONES = [
|
||||||
|
'1F3FB' => 'skin-tone-2',
|
||||||
|
'1F3FC' => 'skin-tone-3',
|
||||||
|
'1F3FD' => 'skin-tone-4',
|
||||||
|
'1F3FE' => 'skin-tone-5',
|
||||||
|
'1F3FF' => 'skin-tone-6'
|
||||||
|
];
|
||||||
|
|
||||||
|
private $map;
|
||||||
|
private $regex;
|
||||||
|
private $dataDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EmojiDetector constructor.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->dataDir = __DIR__ . '/../var';
|
||||||
|
$this->loadMap();
|
||||||
|
$this->loadRawEmojis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $string
|
||||||
|
* @return EmojiInfo[]
|
||||||
|
*/
|
||||||
|
public function detect($string) {
|
||||||
|
|
||||||
|
$oldEncoding = mb_internal_encoding();
|
||||||
|
mb_internal_encoding('UTF-8');
|
||||||
|
|
||||||
|
/** @var EmojiInfo[] $emojiInfos */
|
||||||
|
$emojiInfos = [];
|
||||||
|
|
||||||
|
$matches = [];
|
||||||
|
foreach($this->regex as $icon) {
|
||||||
|
$strpos = mb_strpos($string, $icon);
|
||||||
|
if($strpos !== false) {
|
||||||
|
$matches[] = [$icon, $strpos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = 0;
|
||||||
|
|
||||||
|
foreach($matches as $match) {
|
||||||
|
$emojiInfo = new EmojiInfo();
|
||||||
|
|
||||||
|
$emojiInfo->setEmoji($match[0]);
|
||||||
|
$emojiInfo->setOffset(strpos($string, $match[0]));
|
||||||
|
$emojiInfo->setMbOffset(mb_strpos($string, $match[0]));
|
||||||
|
|
||||||
|
// Break apart the hex characters and build the hex string
|
||||||
|
$hexCodes = [];
|
||||||
|
|
||||||
|
for($i = 0; $i < mb_strlen($emojiInfo->getEmoji()); $i++) {
|
||||||
|
$hexCodes[] = strtoupper(dechex($this->unicodeOrd(mb_substr($match[0], $i, 1))));
|
||||||
|
}
|
||||||
|
$emojiInfo->setHexCodes($hexCodes);
|
||||||
|
|
||||||
|
// Denote the emoji name
|
||||||
|
if(array_key_exists($emojiInfo->getHexString(), $this->map)) {
|
||||||
|
$emojiInfo->setName($this->map[$emojiInfo->getHexString()]['name']);
|
||||||
|
$emojiInfo->setShortName($this->map[$emojiInfo->getHexString()]['shortName']);
|
||||||
|
$emojiInfo->setCategory($this->map[$emojiInfo->getHexString()]['category']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Denote the skin tone
|
||||||
|
foreach($hexCodes as $hexCode) {
|
||||||
|
if(array_key_exists($hexCode, self::SKIN_TONES)) {
|
||||||
|
$emojiInfo->setSkinTone(self::SKIN_TONES[$hexCode]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$length += (strlen($emojiInfo->getEmoji()) - 1);
|
||||||
|
|
||||||
|
$emojiInfos[] = $emojiInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
usort($emojiInfos, function(EmojiInfo $a, EmojiInfo $b) {
|
||||||
|
if($a->getOffset() == $b->getOffset()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return $a->getOffset() < $b->getOffset() ? -1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
/** @var EmojiInfo[] $data */
|
||||||
|
$data = [];
|
||||||
|
foreach($emojiInfos as $emoji) {
|
||||||
|
if(count($data) == 0) {
|
||||||
|
$data[] = $emoji;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var EmojiInfo $last */
|
||||||
|
$last = end($data);
|
||||||
|
$key = key($data);
|
||||||
|
|
||||||
|
if($last->getOffset() == $emoji->getOffset()) {
|
||||||
|
if($last->getMbLength() < $emoji->getMbLength()) {
|
||||||
|
$data[$key] = $emoji;
|
||||||
|
}
|
||||||
|
} else if($emoji->getOffset() >= strlen($last->getEmoji()) + $last->getOffset()) {
|
||||||
|
$data[] = $emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
mb_internal_encoding($oldEncoding);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isSingleEmoji($string) {
|
||||||
|
if(mb_strlen($string) > self::LONGEST_EMOJI) return false;
|
||||||
|
|
||||||
|
$emojis = $this->detect($string);
|
||||||
|
if(count($emojis) !== 1) return false;
|
||||||
|
|
||||||
|
$emoji = array_pop($emojis);
|
||||||
|
$string = str_replace($emoji->getEmoji(), '', $string);
|
||||||
|
|
||||||
|
$split = $this->str_split_unicode($string);
|
||||||
|
if(count($split) > 1) return false;
|
||||||
|
else if(count($split) === 1 && $split[0] === '') return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadMap() {
|
||||||
|
$mapFile = $this->dataDir . '/map.json';
|
||||||
|
if(!file_exists($mapFile)) {
|
||||||
|
throw new Exception("Could not load Emoji map file");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->map = json_decode(file_get_contents($mapFile), true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadRawEmojis() {
|
||||||
|
$mapFile = $this->dataDir . '/raw.json';
|
||||||
|
if(!file_exists($mapFile)) {
|
||||||
|
throw new Exception("Could not load Emoji raw file");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->regex = json_decode(file_get_contents($mapFile), true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $hexChar
|
||||||
|
* @return bool|int
|
||||||
|
*/
|
||||||
|
private function unicodeOrd($hexChar) {
|
||||||
|
$ord0 = ord($hexChar[0]);
|
||||||
|
if($ord0 >= 0 && $ord0 <= 127) return $ord0;
|
||||||
|
|
||||||
|
$ord1 = ord($hexChar[1]);
|
||||||
|
if($ord0 >= 192 && $ord0 <= 223) return ($ord0 - 192) * 64 + ($ord1 - 128);
|
||||||
|
|
||||||
|
$ord2 = ord($hexChar[2]);
|
||||||
|
if($ord0 >= 224 && $ord0 <= 239) return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128);
|
||||||
|
|
||||||
|
$ord3 = ord($hexChar[3]);
|
||||||
|
if($ord0 >= 240 && $ord0 <= 247) return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2 - 128) * 64 + ($ord3 - 128);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $str
|
||||||
|
* @param int $l
|
||||||
|
* @return false|string[]
|
||||||
|
*/
|
||||||
|
private function str_split_unicode($str, $l = 0) {
|
||||||
|
if ($l > 0) {
|
||||||
|
$ret = array();
|
||||||
|
$len = mb_strlen($str, "UTF-8");
|
||||||
|
for ($i = 0; $i < $len; $i += $l) {
|
||||||
|
$ret[] = mb_substr($str, $i, $l, "UTF-8");
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
167
user/EmojiDetectorTest.php
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SteppingHat\Test\EmojiDetector;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use SteppingHat\EmojiDetector\EmojiDetector;
|
||||||
|
|
||||||
|
class EmojiDetectorTest extends TestCase {
|
||||||
|
|
||||||
|
public function testDetectEmoji() {
|
||||||
|
$string = '🍆';
|
||||||
|
$emojis = (new EmojiDetector())->detect($string);
|
||||||
|
|
||||||
|
$this->assertCount(1, $emojis);
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('🍆', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('eggplant', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('food-vegetable', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('Food & Drink', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertSame(1, $emoji->getMbLength(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertNull($emoji->getSkinTone(), "Emoji object contains a skin tone when none should exist");
|
||||||
|
$this->assertSame(0, $emoji->getOffset(), "Emoji is indicating a position other than the start of the string");
|
||||||
|
$this->assertSame(0, $emoji->getMbOffset(), "Emoji is indicating a position other than the start of the string");
|
||||||
|
$this->assertSame(['1F346'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function testDetectSimpleEmoji() {
|
||||||
|
$string = '❤️';
|
||||||
|
$emojis = (new EmojiDetector())->detect($string);
|
||||||
|
|
||||||
|
$this->assertCount(1, $emojis);
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('❤️', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('red heart', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('emotion', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('Smileys & Emotion', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertSame(2, $emoji->getMbLength(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertNull($emoji->getSkinTone(), "Emoji object contains a skin tone when none should exist");
|
||||||
|
$this->assertSame(0, $emoji->getOffset(), "Emoji is indicating a position other than the start of the string");
|
||||||
|
$this->assertSame(0, $emoji->getMbOffset(), "Emoji is indicating a position other than the start of the string");
|
||||||
|
$this->assertSame(['2764', 'FE0F'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDetectEmojiInString() {
|
||||||
|
$string = 'LOL 😂!';
|
||||||
|
$emojis = (new EmojiDetector())->detect($string);
|
||||||
|
|
||||||
|
$this->assertCount(1, $emojis);
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('😂', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('face with tears of joy', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('face-smiling', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('Smileys & Emotion', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertSame(1, $emoji->getMbLength(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertNull($emoji->getSkinTone(), "Emoji object contains a skin tone when none should exist");
|
||||||
|
$this->assertSame(4, $emoji->getOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(4, $emoji->getMbOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(['1F602'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDetectMultipleEmoji() {
|
||||||
|
$string = '🌚💩';
|
||||||
|
$emojis = (new EmojiDetector())->detect($string);
|
||||||
|
|
||||||
|
$this->assertCount(2, $emojis);
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('🌚', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('new moon face', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('sky & weather', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('Travel & Places', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertCount(1, $emoji->getHexCodes(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertNull($emoji->getSkinTone(), "Emoji object contains a skin tone when none should exist");
|
||||||
|
$this->assertSame(0, $emoji->getOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(0, $emoji->getMbOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(['1F31A'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('💩', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('pile of poo', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('face-costume', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('Smileys & Emotion', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertSame(1, $emoji->getMbLength(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertNull($emoji->getSkinTone(), "Emoji object contains a skin tone when none should exist");
|
||||||
|
$this->assertSame(4, $emoji->getOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(1, $emoji->getMbOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(['1F4A9'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDetectSkinToneEmoji() {
|
||||||
|
$string = '🤦🏻';
|
||||||
|
$emojis = (new EmojiDetector())->detect($string);
|
||||||
|
|
||||||
|
$this->assertCount(1, $emojis);
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('🤦🏻', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('person facepalming: light skin tone', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('person-gesture', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('People & Body', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertCount(2, $emoji->getHexCodes(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertSame('skin-tone-2', $emoji->getSkinTone(), "Emoji reported a different skin tone than expected");
|
||||||
|
$this->assertSame(0, $emoji->getOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(0, $emoji->getMbOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(['1F926', '1F3FB'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDetectComplexString() {
|
||||||
|
$string = 'I ❤️ working on 👨💻';
|
||||||
|
$emojis = (new EmojiDetector())->detect($string);
|
||||||
|
|
||||||
|
$this->assertCount(2, $emojis);
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('❤️', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('red heart', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('emotion', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('Smileys & Emotion', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertCount(2, $emoji->getHexCodes(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertSame(null, $emoji->getSkinTone(), "Emoji reported a different skin tone than expected");
|
||||||
|
$this->assertSame(2, $emoji->getOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(2, $emoji->getMbOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(['2764', 'FE0F'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
|
||||||
|
$emoji = array_shift($emojis);
|
||||||
|
|
||||||
|
$this->assertSame('👨💻', $emoji->getEmoji(), "Expected emoji does not match actual emoji in string");
|
||||||
|
$this->assertSame('man technologist', $emoji->getName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('person-role', $emoji->getShortName(), "Expected emoji name does not match the actual emoji name");
|
||||||
|
$this->assertSame('People & Body', $emoji->getCategory(), "Expected emoji category does not match the actual emoji category");
|
||||||
|
$this->assertCount(3, $emoji->getHexCodes(), "More emoji characters in the hex string are present than expected");
|
||||||
|
$this->assertSame(null, $emoji->getSkinTone(), "Emoji reported a different skin tone than expected");
|
||||||
|
$this->assertSame(20, $emoji->getOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(16, $emoji->getMbOffset(), "Emoji is indicating a position that is not expected");
|
||||||
|
$this->assertSame(['1F468', '200D', '1F4BB'], $emoji->getHexCodes(), "Invalid hex codes representing the emoji were presented");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleEmoji() {
|
||||||
|
$detector = new EmojiDetector();
|
||||||
|
|
||||||
|
$string = '🖥';
|
||||||
|
$this->assertTrue($detector->isSingleEmoji($string));
|
||||||
|
|
||||||
|
$string = '😂🎉';
|
||||||
|
$this->assertFalse($detector->isSingleEmoji($string));
|
||||||
|
|
||||||
|
$string = '👨💻'; // This one has a ZWJ character
|
||||||
|
$this->assertTrue($detector->isSingleEmoji($string));
|
||||||
|
|
||||||
|
$string = '👨💻'; // This one does not have a ZWJ character
|
||||||
|
$this->assertFalse($detector->isSingleEmoji($string));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
186
user/EmojiInfo.php
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SteppingHat\EmojiDetector\Model;
|
||||||
|
|
||||||
|
class EmojiInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The emoji characters
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $emoji;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A friendly emoji name
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An even friendlier emoji name
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $shortName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The category of the emoji
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The detected skin tone variation (if present)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $skinTone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of individual UTF-8 hex characters that make up the emoji
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $hexCodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset of the emoji in the parent string if present
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The multibyte offset
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $mbOffset;
|
||||||
|
|
||||||
|
public function __toString() {
|
||||||
|
return $this->getEmoji();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEmoji() {
|
||||||
|
return $this->emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $emoji
|
||||||
|
*/
|
||||||
|
public function setEmoji($emoji) {
|
||||||
|
$this->emoji = $emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName() {
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function setName($name) {
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getShortName() {
|
||||||
|
return $this->shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $shortName
|
||||||
|
*/
|
||||||
|
public function setShortName($shortName) {
|
||||||
|
$this->shortName = $shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCategory() {
|
||||||
|
return $this->category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $category
|
||||||
|
*/
|
||||||
|
public function setCategory($category) {
|
||||||
|
$this->category = $category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSkinTone() {
|
||||||
|
return $this->skinTone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $skinTone
|
||||||
|
*/
|
||||||
|
public function setSkinTone($skinTone) {
|
||||||
|
$this->skinTone = $skinTone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getHexCodes() {
|
||||||
|
return $this->hexCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $hexCodes
|
||||||
|
*/
|
||||||
|
public function setHexCodes($hexCodes) {
|
||||||
|
$this->hexCodes = $hexCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getOffset() {
|
||||||
|
return $this->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
*/
|
||||||
|
public function setOffset($offset) {
|
||||||
|
$this->offset = $offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getMbOffset() {
|
||||||
|
return $this->mbOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mbOffset
|
||||||
|
*/
|
||||||
|
public function setMbOffset($mbOffset) {
|
||||||
|
$this->mbOffset = $mbOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getMbLength() {
|
||||||
|
if($this->hexCodes === null) return false;
|
||||||
|
else return count($this->hexCodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHexString() {
|
||||||
|
return implode('-', $this->getHexCodes());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
3
user/FUNDING.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: telepathics
|
21
user/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Javan Eskander
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
21
user/LICENSE.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 William Bargent
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
57
user/MapGenerator.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SteppingHat\EmojiDetector;
|
||||||
|
|
||||||
|
class MapGenerator {
|
||||||
|
|
||||||
|
private static $upstreamUrl = 'https://unpkg.com/emoji.json@13.1.0/emoji.json';
|
||||||
|
|
||||||
|
public static function generateMap() {
|
||||||
|
$dataDir = __DIR__."/../var";
|
||||||
|
if(!is_dir($dataDir)) mkdir($dataDir, 0777, true);
|
||||||
|
|
||||||
|
// Load emoji data from amio/emoji.json
|
||||||
|
$emojiData = json_decode(file_get_contents(self::$upstreamUrl), true);
|
||||||
|
|
||||||
|
$mapData = [];
|
||||||
|
$rawEmojis = [];
|
||||||
|
foreach($emojiData as $emoji) {
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => strtolower($emoji['name']),
|
||||||
|
'shortName' => self::getShortName($emoji['category']),
|
||||||
|
'category' => self::getCategory($emoji['category'])
|
||||||
|
];
|
||||||
|
|
||||||
|
$mapData[str_replace(' ', '-', $emoji['codes'])] = $data;
|
||||||
|
|
||||||
|
$rawEmojis[] = $emoji['char'];
|
||||||
|
|
||||||
|
if(isset($emoji['variations'])) {
|
||||||
|
foreach($emoji['variations'] as $variation) {
|
||||||
|
$mapData[$variation] = $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($emoji['skin_variations'])) {
|
||||||
|
foreach($emoji['skin_variations'] as $variation) {
|
||||||
|
$mapData[$variation['unified']] = $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($dataDir."/map.json", json_encode($mapData));
|
||||||
|
file_put_contents($dataDir."/raw.json", json_encode($rawEmojis));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getShortName($string) {
|
||||||
|
preg_match('#\((.*?)\)#', $string, $matches);
|
||||||
|
return str_replace(['(', ')'], '', array_shift($matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getCategory($string) {
|
||||||
|
return substr($string, 0, strpos($string, '(') - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
175
user/README.md
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
PHP Emoji Detector
|
||||||
|
==================
|
||||||
|
|
||||||
|
[](//packagist.org/packages/steppinghat/emoji-detector) [](//packagist.org/packages/steppinghat/emoji-detector) [](//packagist.org/packages/steppinghat/emoji-detector) [](https://travis-ci.com/SteppingHat/php-emoji-detector)
|
||||||
|
|
||||||
|
Have an input string full of emoji's and you want to know detailed information about each emoji?
|
||||||
|
Want to build an easy way to validate emoji's that come in as input data?
|
||||||
|
|
||||||
|
This :clap: is :clap: the :clap: library :clap: you :clap: want!
|
||||||
|
|
||||||
|
## What does this thing do?
|
||||||
|
|
||||||
|
This library simply parses input strings and returns a list of relevant information about emoji's that are present in the string. It currently supports version 12.1 of the emoji standard.
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install this library using composer
|
||||||
|
|
||||||
|
$ composer require steppinghat/emoji-detector
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### The Model
|
||||||
|
|
||||||
|
For most outputs, the library will provide an `EmojiInfo` object that contains all of the relevant information about an emoji.
|
||||||
|
The object will contain the following information:
|
||||||
|
|
||||||
|
| Property | Description |
|
||||||
|
| ----------- | ----------- |
|
||||||
|
| `emoji` | The emoji chacater itself |
|
||||||
|
| `name` | A user friendly name of the specific emoji |
|
||||||
|
| `shortName` | A shortened name of the emoji |
|
||||||
|
| `category` | A user friendly category name for the emoji |
|
||||||
|
| `skinTone` | The level of skin tone of the emoji (if present) |
|
||||||
|
| `hexCodes` | An array of individual hexadecimal characters that are used to make up the emoji |
|
||||||
|
| `offset` | The position in the string where the emoji starts |
|
||||||
|
| `mbOffset` | The multibyte position in the string where the emoji starts |
|
||||||
|
|
||||||
|
All of these properties are protected, but can be accessed by their appropriate getters and setters. E.g. `getCategory()` or `setSkinTone()`.
|
||||||
|
|
||||||
|
|
||||||
|
### Emoji detection
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('vendor/autoload.php');
|
||||||
|
|
||||||
|
use SteppingHat\EmojiDetector;
|
||||||
|
|
||||||
|
$input = "Hello 👋 world!";
|
||||||
|
$detector = EmojiDetector();
|
||||||
|
$emojis = $detector->detect($input);
|
||||||
|
|
||||||
|
print_r($emojis);
|
||||||
|
```
|
||||||
|
This example is the most common usage of the detector, returning an array of objects that provide detailed information about each emoji found in the input string.
|
||||||
|
|
||||||
|
```
|
||||||
|
Array
|
||||||
|
(
|
||||||
|
[0] => SteppingHat\EmojiDetector\Model\EmojiInfo Object
|
||||||
|
(
|
||||||
|
[emoji:protected] => 👋
|
||||||
|
[name:protected] => waving hand
|
||||||
|
[shortName:protected] => hand-fingers-open
|
||||||
|
[category:protected] => People & Body
|
||||||
|
[skinTone:protected] =>
|
||||||
|
[hexCodes:protected] => Array
|
||||||
|
(
|
||||||
|
[0] => 1F44B
|
||||||
|
)
|
||||||
|
|
||||||
|
[offset:protected] => 6
|
||||||
|
[mbOffset:protected] => 6
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
The library has full support for complex emoji's that make use of the ZWJ (Zero Width Joiner) character.
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('vendor/autoload.php');
|
||||||
|
|
||||||
|
use SteppingHat\EmojiDetector;
|
||||||
|
|
||||||
|
$input = "I ❤️ to 👨💻";
|
||||||
|
$detector = new SteppingHat\EmojiDetector\EmojiDetector();
|
||||||
|
$emojis = $detector->detect($input);
|
||||||
|
|
||||||
|
print_r($emojis);
|
||||||
|
```
|
||||||
|
|
||||||
|
The above will produce the following output:
|
||||||
|
|
||||||
|
```
|
||||||
|
Array
|
||||||
|
(
|
||||||
|
[0] => SteppingHat\EmojiDetector\Model\EmojiInfo Object
|
||||||
|
(
|
||||||
|
[emoji:protected] => ❤️
|
||||||
|
[name:protected] => red heart
|
||||||
|
[shortName:protected] => emotion
|
||||||
|
[category:protected] => Smileys & Emotion
|
||||||
|
[skinTone:protected] =>
|
||||||
|
[hexCodes:protected] => Array
|
||||||
|
(
|
||||||
|
[0] => 2764
|
||||||
|
[1] => FE0F
|
||||||
|
)
|
||||||
|
|
||||||
|
[offset:protected] => 2
|
||||||
|
[mbOffset:protected] => 2
|
||||||
|
)
|
||||||
|
|
||||||
|
[1] => SteppingHat\EmojiDetector\Model\EmojiInfo Object
|
||||||
|
(
|
||||||
|
[emoji:protected] => 👨💻
|
||||||
|
[name:protected] => man technologist
|
||||||
|
[shortName:protected] => person-role
|
||||||
|
[category:protected] => People & Body
|
||||||
|
[skinTone:protected] =>
|
||||||
|
[hexCodes:protected] => Array
|
||||||
|
(
|
||||||
|
[0] => 1F468
|
||||||
|
[1] => 200D
|
||||||
|
[2] => 1F4BB
|
||||||
|
)
|
||||||
|
|
||||||
|
[offset:protected] => 13
|
||||||
|
[mbOffset:protected] => 9
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Testing for single emojis
|
||||||
|
|
||||||
|
Sometimes it is handy to test if an input string is a single emoji on it's own.
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once('vendor/autoload.php');
|
||||||
|
|
||||||
|
use SteppingHat\EmojiDetector;
|
||||||
|
|
||||||
|
$detector = new SteppingHat\EmojiDetector\EmojiDetector();
|
||||||
|
|
||||||
|
$detector->isSingleEmoji("💩"); // Returns TRUE
|
||||||
|
$detector->isSingleEmoji("Time to dance 🌚"); // Returns FALSE
|
||||||
|
$detector->isSingleEmoji("🍆🍒"); // Returns FALSE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Included for library development purposes is a small set of test cases to assure that basic library functions work as expected. These tests can be launched by running the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ php vendor/bin/simple-phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Made with :heart: by Javan Eskander
|
||||||
|
|
||||||
|
Available for use under the MIT license.
|
||||||
|
|
||||||
|
Emoji data sourced from [amio/emoji.json](https://github.com/amio/emoji.json)
|
45
user/README.textile
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
h1. YOURLS Pseudonymize Plugin
|
||||||
|
|
||||||
|
This plugin "pseudonymizes" the IP addresses so that it is in line with the German privacy laws.
|
||||||
|
|
||||||
|
This effectively means, that the last segment of an IP address is changed into a 0 ("zero"), thus removed.
|
||||||
|
|
||||||
|
*IPv4 and IPv6 addresses are supported.*
|
||||||
|
|
||||||
|
*NOTE*: Requires PHP >= 5.2.0 due to "filter_var":http://php.net/manual/en/function.filter-var.php usage.
|
||||||
|
|
||||||
|
h2. Download
|
||||||
|
|
||||||
|
Latest version: <a href="https://raw.github.com/ubicoo/yourls-pseudonymize/master/plugin.php">plugin.php</a>
|
||||||
|
|
||||||
|
h2. Install
|
||||||
|
|
||||||
|
Copy plugin.php to *YOURLS_HOME*/user/plugins/yourls-pseudonymize folder and activate via the admin menu.
|
||||||
|
|
||||||
|
h2. Support
|
||||||
|
|
||||||
|
<a href="http://blog.yourls.org/forums/topic/yourls-pseudonymize-plugin/">Discuss about this plugin</a> in the YOURLS forum.
|
||||||
|
|
||||||
|
<a href="https://github.com/ubicoo/yourls-pseudonymize/issues/new">File an issue</a> right here on the GitHub project home.
|
||||||
|
|
||||||
|
h2. MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2010 Ubicoo - http://www.ubicoo.com
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
948
user/_base.scss
Normal file
@ -0,0 +1,948 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800');
|
||||||
|
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
|
||||||
|
|
||||||
|
// Mobile mixin
|
||||||
|
@mixin for-size($range) {
|
||||||
|
$phone-upper-boundary: 900px;
|
||||||
|
$tablet-portrait-upper-boundary: 1100px;
|
||||||
|
$tablet-landscape-upper-boundary: 1200px;
|
||||||
|
$desktop-upper-boundary: 1800px;
|
||||||
|
|
||||||
|
@if $range == phone-only {
|
||||||
|
@media (max-width: #{$phone-upper-boundary - 1}) { @content; }
|
||||||
|
} @else if $range == tablet-portrait-up {
|
||||||
|
@media (min-width: $phone-upper-boundary) { @content; }
|
||||||
|
} @else if $range == tablet-landscape-up {
|
||||||
|
@media (min-width: $tablet-portrait-upper-boundary) { @content; }
|
||||||
|
} @else if $range == desktop-up {
|
||||||
|
@media (min-width: $tablet-landscape-upper-boundary) { @content; }
|
||||||
|
} @else if $range == big-desktop-up {
|
||||||
|
@media (min-width: $desktop-upper-boundary) { @content; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use it like this:
|
||||||
|
// @include for-size(phone-only) {
|
||||||
|
// margin: 30px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//
|
||||||
|
// Globals
|
||||||
|
//
|
||||||
|
body {
|
||||||
|
background-color: $darker;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div, p, td, input, p {
|
||||||
|
font-family: 'Open Sans', sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
color: $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:link, a:active, a:visited {
|
||||||
|
color: #828282;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: darken($title, 20%);
|
||||||
|
transition: 0.4s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 10px;
|
||||||
|
border: none !important;
|
||||||
|
background: $light !important;
|
||||||
|
color: $text !important;
|
||||||
|
font-size: 1em !important;
|
||||||
|
outline: none;
|
||||||
|
margin: 0px 5px !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
border-radius: 3px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button,
|
||||||
|
input.submit,
|
||||||
|
input[type="submit"] {
|
||||||
|
border-left: 7px solid $accent !important;
|
||||||
|
background: $light !important;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: 0.3s all !important;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: $accent !important;
|
||||||
|
border-left: none !important;
|
||||||
|
color: white !important;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to fix this, because I've had to copy this down lower to make it apply to the add URL button
|
||||||
|
input.button:hover,
|
||||||
|
input.submit:hover,
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
background: darken($accent, 15%) !important;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: darken($accent, 15%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="button"]:disabled,
|
||||||
|
input[type="submit"]:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text,
|
||||||
|
input[type="text"] {
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25) !important;
|
||||||
|
transition: 0.4s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
@if ($theme != "light") {
|
||||||
|
input.text:active,
|
||||||
|
input.text:focus {
|
||||||
|
border: 1px solid $accent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 150px;
|
||||||
|
padding: 5px 35px 5px 10px;
|
||||||
|
// font-size: 0.9em;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 26px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
color: $text;
|
||||||
|
background: url(data:image/png;base64,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) 96% / 15% no-repeat $light;
|
||||||
|
margin: 5px 10px;
|
||||||
|
transition: 0.4s all;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
select:hover {
|
||||||
|
background: url(data:image/png;base64,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) 96% / 15% no-repeat $light;
|
||||||
|
}
|
||||||
|
|
||||||
|
#javascript_error {
|
||||||
|
background: red;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End Globals
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notification Bar
|
||||||
|
//
|
||||||
|
.jquery-notify-bar {
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: none;
|
||||||
|
border: none;
|
||||||
|
opacity: 1;
|
||||||
|
box-shadow: none;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 500;
|
||||||
|
position: static;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: -45px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
a, a:link, a:active, a:visited {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar.error,
|
||||||
|
.jquery-notify-bar.fail {
|
||||||
|
background-color: #FF9800;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar.success {
|
||||||
|
color: white;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End Notification Bar
|
||||||
|
|
||||||
|
//
|
||||||
|
// Login page
|
||||||
|
//
|
||||||
|
.login {
|
||||||
|
#wrap {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-logo {
|
||||||
|
width: 150px;
|
||||||
|
margin: 30px auto;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text {
|
||||||
|
width: 270px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button {
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 10px 25px;
|
||||||
|
margin-top: 15px !important;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: $accent !important;
|
||||||
|
} else {
|
||||||
|
background: $light !important;
|
||||||
|
border-left: 7px solid $accent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button:hover {
|
||||||
|
background: darken($accent, 10%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
padding: 10px;
|
||||||
|
background: $accent;
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End login page
|
||||||
|
|
||||||
|
//
|
||||||
|
// Start Index page
|
||||||
|
//
|
||||||
|
.index {
|
||||||
|
#add-url {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new_url_form {
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
// min-width: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new_url {
|
||||||
|
border: none;
|
||||||
|
background: $default;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
input.button {
|
||||||
|
margin-top: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
background: $default;
|
||||||
|
padding: 4px;
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.create {
|
||||||
|
background: $accent !important;
|
||||||
|
width: 150px;
|
||||||
|
font-size: 1.3em !important;
|
||||||
|
border: none !important;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px !important;
|
||||||
|
margin-left: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 50px;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: darken($accent, 10%);
|
||||||
|
} @else {
|
||||||
|
background: $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
color: $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text {
|
||||||
|
width: 360px;
|
||||||
|
padding: 4px;
|
||||||
|
font-weight: 200;
|
||||||
|
font-size: 1em !important;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: $default !important;
|
||||||
|
} @else {
|
||||||
|
background: $lightest !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.short {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#add-keyword {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button {
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1em !important;
|
||||||
|
margin-left: 10px !important;
|
||||||
|
background: $lightest !important;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: $default !important;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $accent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button:hover {
|
||||||
|
background: darken($accent, 10%) !important;
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: darken(white, 10%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#new_url_form {
|
||||||
|
margin-left: 260px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table stuff
|
||||||
|
table.tblSorter {
|
||||||
|
background-color: $default;
|
||||||
|
color: $text;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
small a {
|
||||||
|
color: darken(white, 50%)
|
||||||
|
}
|
||||||
|
|
||||||
|
thead tr .tablesorter-header {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tfoot tr {
|
||||||
|
background-color: $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead tr th,
|
||||||
|
tfoot tr th,
|
||||||
|
th.header {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
/* font-size: 8pt; */
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead tr .tablesorter-headerAsc,
|
||||||
|
thead tr .tablesorter-headerDesc {
|
||||||
|
background-color: $lightest !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody td {
|
||||||
|
color: $text;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: $light;
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: 0.4s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:hover td {
|
||||||
|
background-color: $lightest !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr.normal-row td {
|
||||||
|
background: $light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword {
|
||||||
|
border-left: 7px solid $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text {
|
||||||
|
padding: 5px;
|
||||||
|
margin: 8px 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation .nav_link a {
|
||||||
|
background: $light;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $lightest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.edit-row td {
|
||||||
|
background: $default !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
$icons-list: stats, share, edit, delete;
|
||||||
|
@each $icon in $icons-list {
|
||||||
|
@if $icon == delete {
|
||||||
|
td.actions .button_#{$icon} {
|
||||||
|
background: red url(../img/#{$icon}.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken(red, 10%) url(../img/#{$icon}.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
td.actions .button_#{$icon} {
|
||||||
|
background: $accent url(../img/#{$icon}.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken($accent, 10%) url(../img/#{$icon}.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End index page
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Nav
|
||||||
|
//
|
||||||
|
nav {
|
||||||
|
background: $default;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 50px 30px;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
li#admin_menu_logout_link {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#admin_menu li:hover {
|
||||||
|
list-style-type: none;
|
||||||
|
color: darken($title, 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#admin_menu li {
|
||||||
|
color: $title;
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin_menu_logout_link:hover {
|
||||||
|
color: $title !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin_menu_sublevel {
|
||||||
|
font-weight: 100;
|
||||||
|
margin-left: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.material-icons {
|
||||||
|
font-size: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img.logo {
|
||||||
|
width: 90px;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: $accent;
|
||||||
|
padding: 9px 150px 8px 20px;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open {
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 30;
|
||||||
|
padding: 10px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End nav
|
||||||
|
|
||||||
|
//
|
||||||
|
// Information
|
||||||
|
//
|
||||||
|
#wrap {
|
||||||
|
#tabs {
|
||||||
|
min-width: 580px;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
background: $light !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrap_unfloat {
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#headers {
|
||||||
|
border: none;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
#historical_clicks li:hover {
|
||||||
|
background: darken($default, 10%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#headers li a,
|
||||||
|
#stats_lines li a {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background: $light;
|
||||||
|
color: $text;
|
||||||
|
padding: 10px 15px 7px 25px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken($default, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background: $lightest;
|
||||||
|
border-bottom: 2px solid $accent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken($default, 15%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#stats_lines li a {
|
||||||
|
padding: 7px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.toggle_display {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
ellipse {
|
||||||
|
fill: $accent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// General Styles
|
||||||
|
//
|
||||||
|
|
||||||
|
body.index #wrap {
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap {
|
||||||
|
background: none;
|
||||||
|
margin-left: 270px;
|
||||||
|
border: none;
|
||||||
|
color: $text;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
width: calc(100% - 22px);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: $accent;
|
||||||
|
border: 1px solid $accent;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#shareboxes {
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sharebox {
|
||||||
|
width: 558px;
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share {
|
||||||
|
background: $default;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
padding: 0px 20px 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
background: $light;
|
||||||
|
color: $text;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
outline: none;
|
||||||
|
margin: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#charcount {
|
||||||
|
padding-left: 5px;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
#share_links a {
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap,
|
||||||
|
.plugins main,
|
||||||
|
.plugin_page_sleeky_settings main,
|
||||||
|
code {
|
||||||
|
background: $default;
|
||||||
|
padding: 10px;
|
||||||
|
padding: 5px 25px;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
span {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
tt {
|
||||||
|
background: rgba(0, 123, 255, 0.7);
|
||||||
|
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: rgba(35, 185, 222, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.bookmarklet {
|
||||||
|
border: none;
|
||||||
|
background: #ffffff url(/images/favicon.gif) 4px center no-repeat;
|
||||||
|
color: #3c3c3c;
|
||||||
|
border-radius: 1px;
|
||||||
|
padding: 7px 7px 7px 25px;
|
||||||
|
color: darken(white, 80%) !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #e0e0e0 url(/images/favicon.gif) 4px center no-repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table
|
||||||
|
table.tblSorter {
|
||||||
|
background: $default;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $text;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: darken($text, 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thead tr th,
|
||||||
|
tfoot tr th,
|
||||||
|
th.header {
|
||||||
|
border: none;
|
||||||
|
background-color: $light;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody td {
|
||||||
|
background: $lightest;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#filter_options {
|
||||||
|
padding: 0px 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body > div > pre {
|
||||||
|
overflow-x: scroll;
|
||||||
|
padding-left: 290px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End General Styles
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Footer
|
||||||
|
//
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 230px;
|
||||||
|
color: #828282;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
p {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1em;
|
||||||
|
|
||||||
|
a {
|
||||||
|
background: none;
|
||||||
|
padding-left: 0;
|
||||||
|
color: $text;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #828282;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End footer
|
||||||
|
|
||||||
|
// Mobile styles
|
||||||
|
@include for-size(phone-only) {
|
||||||
|
body.index #wrap {
|
||||||
|
padding-top: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.tools #wrap,
|
||||||
|
body.plugins #wrap,
|
||||||
|
body.plugin_page_sleeky_settings #wrap {
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
|
#wrap {
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
main {
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img.logo {
|
||||||
|
padding: 9px 100% 8px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
height: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 0;
|
||||||
|
|
||||||
|
ul#admin_menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 50px;
|
||||||
|
display: none;
|
||||||
|
@if ($theme == "light") {
|
||||||
|
background: darken($accent, 10%);
|
||||||
|
} @else {
|
||||||
|
background: $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:link, a:active, a:visited {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
.top {
|
||||||
|
display: block;
|
||||||
|
margin-top: 50px;
|
||||||
|
width: 100vw;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new_url_form {
|
||||||
|
min-width: unset;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.short {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#add-url,
|
||||||
|
#add-keyword {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
margin: 10px 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.tblSorter {
|
||||||
|
min-width: 600px;
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
$icons-list: stats, share, edit, delete;
|
||||||
|
@each $icon in $icons-list {
|
||||||
|
td.actions .button_#{$icon} {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#copybox {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar {
|
||||||
|
margin-top: 210px;
|
||||||
|
margin-bottom: -210px;
|
||||||
|
width: calc(100vw - 20px);
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin-left: -30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infos #wrap {
|
||||||
|
margin-top: 30px;
|
||||||
|
|
||||||
|
|
||||||
|
#headers {
|
||||||
|
li {
|
||||||
|
margin: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.infos #tabs {
|
||||||
|
min-width: initial;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#headers {
|
||||||
|
margin: 20px 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
a {
|
||||||
|
padding: 10px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body > div > pre {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
60
user/admin-page.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Google Safe Browsing Lookup admin page
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Display admin page
|
||||||
|
function ozh_yourls_gsb_display_page() {
|
||||||
|
|
||||||
|
// Check if a form was submitted
|
||||||
|
if( isset( $_POST['ozh_yourls_gsb'] ) ) {
|
||||||
|
// Check nonce
|
||||||
|
yourls_verify_nonce( 'gsb_page' );
|
||||||
|
|
||||||
|
// Process form
|
||||||
|
ozh_yourls_gsb_update_option();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get value from database
|
||||||
|
$ozh_yourls_gsb = yourls_get_option( 'ozh_yourls_gsb' );
|
||||||
|
|
||||||
|
// Create nonce
|
||||||
|
$nonce = yourls_create_nonce( 'gsb_page' );
|
||||||
|
|
||||||
|
echo <<<HTML
|
||||||
|
<h2>Google Safe Browsing API Key</h2>
|
||||||
|
|
||||||
|
<p>Google requires you to have a <strong>Google account</strong> and a Safe Browsing <strong>API key</strong>
|
||||||
|
to use their <a href="https://developers.google.com/safe-browsing/lookup_guide">Safe Browsing Lookup Service</a>.</p>
|
||||||
|
<p>Get your API key here: <a href="https://developers.google.com/safe-browsing/key_signup">https://developers.google.com/safe-browsing/key_signup</a></p>
|
||||||
|
|
||||||
|
<h3>Disclaimer from Google</h3>
|
||||||
|
<p>Google works to provide the most accurate and up-to-date phishing and malware information. However, it cannot
|
||||||
|
guarantee that its information is comprehensive and error-free: some risky sites may not be identified, and some safe
|
||||||
|
sites may be identified in error.</p>
|
||||||
|
|
||||||
|
<h3>Configure the plugin</h3>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="nonce" value="$nonce" />
|
||||||
|
<p><label for="ozh_yourls_gsb">API Key</label> <input type="text" id="ozh_yourls_gsb" name="ozh_yourls_gsb" value="$ozh_yourls_gsb" size="70" /></p>
|
||||||
|
<p><input type="submit" value="Update value" /></p>
|
||||||
|
</form>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update option in database
|
||||||
|
function ozh_yourls_gsb_update_option() {
|
||||||
|
$in = $_POST['ozh_yourls_gsb'];
|
||||||
|
|
||||||
|
if( $in ) {
|
||||||
|
// Validate ozh_yourls_gsb: alpha & digits
|
||||||
|
$in = preg_replace( '/[^a-zA-Z0-9-_]/', '', $in );
|
||||||
|
|
||||||
|
// Update value in database
|
||||||
|
yourls_update_option( 'ozh_yourls_gsb', $in );
|
||||||
|
|
||||||
|
yourls_redirect( yourls_admin_url( 'plugins.php?page=ozh_yourls_gsb' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
3188
user/animate.min.css
vendored
Normal file
7
user/autoload.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInitb527cf0f410cc8001ea07d072eb1427c::getLoader();
|
9
user/autoload_classmap.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
9
user/autoload_namespaces.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
10
user/autoload_psr4.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'SteppingHat\\EmojiDetector\\' => array($vendorDir . '/steppinghat/emoji-detector/src'),
|
||||||
|
);
|
55
user/autoload_real.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInitb527cf0f410cc8001ea07d072eb1427c
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInitb527cf0f410cc8001ea07d072eb1427c', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInitb527cf0f410cc8001ea07d072eb1427c', 'loadClassLoader'));
|
||||||
|
|
||||||
|
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||||
|
if ($useStaticLoader) {
|
||||||
|
require_once __DIR__ . '/autoload_static.php';
|
||||||
|
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInitb527cf0f410cc8001ea07d072eb1427c::getInitializer($loader));
|
||||||
|
} else {
|
||||||
|
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||||
|
foreach ($map as $namespace => $path) {
|
||||||
|
$loader->set($namespace, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = require __DIR__ . '/autoload_psr4.php';
|
||||||
|
foreach ($map as $namespace => $path) {
|
||||||
|
$loader->setPsr4($namespace, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||||
|
if ($classMap) {
|
||||||
|
$loader->addClassMap($classMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
31
user/autoload_static.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInitb527cf0f410cc8001ea07d072eb1427c
|
||||||
|
{
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
'S' =>
|
||||||
|
array (
|
||||||
|
'SteppingHat\\EmojiDetector\\' => 26,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'SteppingHat\\EmojiDetector\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/steppinghat/emoji-detector/src',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInitb527cf0f410cc8001ea07d072eb1427c::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInitb527cf0f410cc8001ea07d072eb1427c::$prefixDirsPsr4;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
71
user/blockpage.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
// Project Honeypot http:BL plugin for Yourls - URL Shortener ~ Block Page Template
|
||||||
|
// Copyright (c) 2016, Josh Panter
|
||||||
|
|
||||||
|
// No direct call
|
||||||
|
if( !defined( 'YOURLS_ABSPATH' ) ) die();
|
||||||
|
header('HTTP/1.0 403 Forbidden');
|
||||||
|
?>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>ALERT!</title>
|
||||||
|
<link rel="icon" href="%img%" type="image/png" />
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -- USE LOCAL CACHE
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/spacelab/bootstrap.min.css" rel="stylesheet" integrity="sha384-L/tgI3wSsbb3f/nW9V6Yqlaw3Gj7mpE56LWrhew/c8MIhAYWZ/FNirA64AVkB5pI" crossorigin="anonymous"> -->
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -- LOCAL CACHE -->
|
||||||
|
<link href="%css%" rel="stylesheet" integrity="sha384-L/tgI3wSsbb3f/nW9V6Yqlaw3Gj7mpE56LWrhew/c8MIhAYWZ/FNirA64AVkB5pI" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<!-- Add extra support of older browsers -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="padding:15px 0px 0px 0px;" class="col-md-6 col-md-offset-3">
|
||||||
|
<div style="text-align: center;" class="well well-lg">
|
||||||
|
<div style="display: inline-block; text-align: left">
|
||||||
|
|
||||||
|
<h2 class="text-danger" style="text-align:center;"><img src="%img%" width="30" height="30"/> Forbidden: Access Denied <img src="%img%" width="30" height="30"/></h2>
|
||||||
|
</br>
|
||||||
|
<p>Your IP: <strong>%ip%</strong>, has been flagged by <a href='https://www.projecthoneypot.org' target='_blank'>Project Honey Pot</a> due to the following:
|
||||||
|
<ul>
|
||||||
|
<li>Behavior Type: <strong>%typemeaning%</strong></li>
|
||||||
|
<li>Threat Level: <strong>%threat%</strong></li>
|
||||||
|
</ul>
|
||||||
|
<p>Information regarding threat levels can be found <a href="https://www.projecthoneypot.org/threat_info.php" target="_blank">here</a>.</p>
|
||||||
|
%greyList%
|
||||||
|
<p style="display:none;">Otherwise, please have fun with <a href="http://planetozh.com/smelly.php">this page</a></p>
|
||||||
|
<p>Thank you.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function setcookie( name, value, expires, path, domain, secure ) {
|
||||||
|
// set time, it's in milliseconds
|
||||||
|
var today = new Date();
|
||||||
|
today.setTime( today.getTime() );
|
||||||
|
|
||||||
|
if ( expires ) {
|
||||||
|
expires = expires * 1000 * 60 * 60 * 24;
|
||||||
|
}
|
||||||
|
var expires_date = new Date( today.getTime() + (expires) );
|
||||||
|
|
||||||
|
document.cookie = name + "=" +escape( value ) +
|
||||||
|
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
|
||||||
|
( ( path ) ? ";path=" + path : "" ) +
|
||||||
|
( ( domain ) ? ";domain=" + domain : "" ) +
|
||||||
|
( ( secure ) ? ";secure" : "" );
|
||||||
|
}
|
||||||
|
function letmein() {
|
||||||
|
setcookie('notabot','true',1,'/', '', '');
|
||||||
|
location.reload(true);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</footer>
|
||||||
|
</html>
|
11
user/bootstrap.min.css
vendored
Normal file
106
user/class-gsb.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Google Safe Browsing Lookup client for YOURLS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ozh_yourls_GSB {
|
||||||
|
|
||||||
|
const PROTOCOL_VER = '4.0';
|
||||||
|
const CLIENT = 'yourls-plugin-gsb';
|
||||||
|
const APP_VER = '1.0';
|
||||||
|
|
||||||
|
private $url = '';
|
||||||
|
private $api_key = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor : checks that plugin is properly configured
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct( $api_key ) {
|
||||||
|
$this->api_key = $api_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a URL is blacklisted against GSB Lookup API
|
||||||
|
*
|
||||||
|
* The function returns an array of a boolean and a string.
|
||||||
|
* The boolean indicates whether $this->url is blacklisted (true) or not blacklisted (false)
|
||||||
|
* The string gives diagnosis details: reason of blacklisting, null if clear, or an error message if applicable
|
||||||
|
*
|
||||||
|
* @return array array of boolean ( is blacklisted, description )
|
||||||
|
*/
|
||||||
|
public function is_blacklisted( $url ) {
|
||||||
|
if( !$this->api_key ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->url = urlencode( yourls_sanitize_url( $url ) );
|
||||||
|
if( !$this->url ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $this->request();
|
||||||
|
|
||||||
|
switch( $request->status_code ) {
|
||||||
|
case 200:
|
||||||
|
$response = json_decode($request->body);
|
||||||
|
$blacklisted = true;
|
||||||
|
if (!isset($response->matches))
|
||||||
|
$blacklisted = false;
|
||||||
|
return array($blacklisted, ($blacklisted ? $response->matches[0]->threatType : null));
|
||||||
|
|
||||||
|
case 400:
|
||||||
|
return array( false, 'Could not check Google Safe Browsing: Bad Request' );
|
||||||
|
|
||||||
|
case 403:
|
||||||
|
return array( false, 'Could not check Google Safe Browsing: API key not authorized' );
|
||||||
|
|
||||||
|
case 503:
|
||||||
|
return array( false, 'Could not check Google Safe Browsing: service unavailable' );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP request wrapper
|
||||||
|
*
|
||||||
|
* @return Request request object
|
||||||
|
*/
|
||||||
|
private function request() {
|
||||||
|
$api_url = sprintf( 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=%s',
|
||||||
|
$this->api_key
|
||||||
|
);
|
||||||
|
|
||||||
|
// Request headers
|
||||||
|
$headers = array(
|
||||||
|
'Content-Type' => 'application/json'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Request data
|
||||||
|
$data = array(
|
||||||
|
'client' => array(
|
||||||
|
'clientId' => self::CLIENT,
|
||||||
|
'clientVersion' => self::APP_VER
|
||||||
|
),
|
||||||
|
'threatInfo' => array(
|
||||||
|
'threatTypes' => array('MALWARE', 'SOCIAL_ENGINEERING', 'POTENTIALLY_HARMFUL_APPLICATION', 'UNWANTED_SOFTWARE'),
|
||||||
|
'platformTypes' => array('ANY_PLATFORM'),
|
||||||
|
'threatEntryTypes' => array('URL'),
|
||||||
|
'threatEntries' => array(
|
||||||
|
array(
|
||||||
|
'url' => $this->url
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Request options ?
|
||||||
|
$options = array(
|
||||||
|
);
|
||||||
|
|
||||||
|
return yourls_http_post( $api_url, $headers, json_encode($data), $options );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
user/composer.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "steppinghat/emoji-detector",
|
||||||
|
"description": "Detect and validate emoji in an input string",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/steppinghat/emoji-detector",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Javan Eskander",
|
||||||
|
"homepage": "https://javaneskander.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"SteppingHat\\EmojiDetector\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-json": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/phpunit-bridge": "^5.0@dev"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"generate-map": "SteppingHat\\EmojiDetector\\MapGenerator::generateMap"
|
||||||
|
}
|
||||||
|
}
|
177
user/composer.lock
generated
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "3789659f661fab9f84bee01c2c0c359e",
|
||||||
|
"packages": [],
|
||||||
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "symfony/deprecation-contracts",
|
||||||
|
"version": "dev-main",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||||
|
"reference": "49dc45a74cbac5fffc6417372a9f5ae1682ca0b4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/49dc45a74cbac5fffc6417372a9f5ae1682ca0b4",
|
||||||
|
"reference": "49dc45a74cbac5fffc6417372a9f5ae1682ca0b4",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "2.4-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/contracts",
|
||||||
|
"url": "https://github.com/symfony/contracts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"function.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A generic function and convention to trigger deprecation notices",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/deprecation-contracts/tree/main"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-02-25T16:38:04+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/phpunit-bridge",
|
||||||
|
"version": "5.x-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/phpunit-bridge.git",
|
||||||
|
"reference": "b556f2a53490b04a8645569531c31e54f0abafc5"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/b556f2a53490b04a8645569531c31e54f0abafc5",
|
||||||
|
"reference": "b556f2a53490b04a8645569531c31e54f0abafc5",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1.3",
|
||||||
|
"symfony/deprecation-contracts": "^2.1"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"phpunit/phpunit": "<7.5|9.1.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/error-handler": "^4.4|^5.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader"
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"bin": [
|
||||||
|
"bin/simple-phpunit"
|
||||||
|
],
|
||||||
|
"type": "symfony-bridge",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"name": "phpunit/phpunit",
|
||||||
|
"url": "https://github.com/sebastianbergmann/phpunit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Bridge\\PhpUnit\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides utilities for PHPUnit, especially user deprecation notices management",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/phpunit-bridge/tree/5.x"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-03-17T17:02:51+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"stability-flags": {
|
||||||
|
"symfony/phpunit-bridge": 20
|
||||||
|
},
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": {
|
||||||
|
"php": ">=7.0",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-json": "*"
|
||||||
|
},
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.0.0"
|
||||||
|
}
|
104
user/config.php
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
/* This is a sample config file.
|
||||||
|
* Edit this file with your own settings and save it as "config.php"
|
||||||
|
*
|
||||||
|
* IMPORTANT: edit and save this file as plain ASCII text, using a text editor, for instance TextEdit on Mac OS or
|
||||||
|
* Notepad on Windows. Make sure there is no character before the opening <?php at the beginning of this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** MySQL settings - You can get this info from your web host
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** MySQL database username */
|
||||||
|
define( 'YOURLS_DB_USER', '' );
|
||||||
|
|
||||||
|
/** MySQL database password */
|
||||||
|
define( 'YOURLS_DB_PASS', '' );
|
||||||
|
|
||||||
|
/** The name of the database for YOURLS
|
||||||
|
** Use lower case letters [a-z], digits [0-9] and underscores [_] only */
|
||||||
|
define( 'YOURLS_DB_NAME', '' );
|
||||||
|
|
||||||
|
/** MySQL hostname.
|
||||||
|
** If using a non standard port, specify it like 'hostname:port', e.g. 'localhost:9999' or '127.0.0.1:666' */
|
||||||
|
define( 'YOURLS_DB_HOST', 'localhost' );
|
||||||
|
|
||||||
|
/** MySQL tables prefix
|
||||||
|
** YOURLS will create tables using this prefix (eg `yourls_url`, `yourls_options`, ...)
|
||||||
|
** Use lower case letters [a-z], digits [0-9] and underscores [_] only */
|
||||||
|
define( 'YOURLS_DB_PREFIX', 'yourls_' );
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Site options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** YOURLS installation URL
|
||||||
|
** All lowercase, no trailing slash at the end.
|
||||||
|
** If you define it to "http://sho.rt", don't use "http://www.sho.rt" in your browser (and vice-versa)
|
||||||
|
** To use an IDN domain (eg http://héhé.com), write its ascii form here (eg http://xn--hh-bjab.com) */
|
||||||
|
define( 'YOURLS_SITE', '' );
|
||||||
|
|
||||||
|
/** YOURLS language
|
||||||
|
** Change this setting to use a translation file for your language, instead of the default English.
|
||||||
|
** That translation file (a .mo file) must be installed in the user/language directory.
|
||||||
|
** See http://yourls.org/translations for more information */
|
||||||
|
define( 'YOURLS_LANG', '' );
|
||||||
|
|
||||||
|
/** Allow multiple short URLs for a same long URL
|
||||||
|
** Set to true to have only one pair of shortURL/longURL (default YOURLS behavior)
|
||||||
|
** Set to false to allow multiple short URLs pointing to the same long URL (bit.ly behavior) */
|
||||||
|
define( 'YOURLS_UNIQUE_URLS', false );
|
||||||
|
|
||||||
|
/** Private means the Admin area will be protected with login/pass as defined below.
|
||||||
|
** Set to false for public usage (eg on a restricted intranet or for test setups)
|
||||||
|
** Read http://yourls.org/privatepublic for more details if you're unsure */
|
||||||
|
define( 'YOURLS_PRIVATE', true );
|
||||||
|
|
||||||
|
/** A random secret hash used to encrypt cookies. You don't have to remember it, make it long and complicated
|
||||||
|
** Hint: copy from http://yourls.org/cookie */
|
||||||
|
define( 'YOURLS_COOKIEKEY', '' );
|
||||||
|
|
||||||
|
|
||||||
|
/** Username(s) and password(s) allowed to access the site. Passwords either in plain text or as encrypted hashes
|
||||||
|
** YOURLS will auto encrypt plain text passwords in this file
|
||||||
|
** Read http://yourls.org/userpassword for more information */
|
||||||
|
$yourls_user_passwords = [
|
||||||
|
'admin' => '' /* Password encrypted by YOURLS */ /* Password encrypted by YOURLS */ ,
|
||||||
|
// You can have one or more 'login'=>'password' lines
|
||||||
|
];
|
||||||
|
|
||||||
|
/** URL shortening method: either 36 or 62
|
||||||
|
** 36: generates all lowercase keywords (ie: 13jkm)
|
||||||
|
** 62: generates mixed case keywords (ie: 13jKm or 13JKm)
|
||||||
|
** For more information, see https://yourls.org/urlconvert */
|
||||||
|
define( 'YOURLS_URL_CONVERT', 36 );
|
||||||
|
|
||||||
|
/** Debug mode to output some internal information
|
||||||
|
** Default is false for live site. Enable when coding or before submitting a new issue */
|
||||||
|
define( 'YOURLS_DEBUG', false );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserved keywords (so that generated URLs won't match them)
|
||||||
|
* Define here negative, unwanted or potentially misleading keywords.
|
||||||
|
*/
|
||||||
|
$yourls_reserved_URL = [
|
||||||
|
'porn', 'faggot', 'sex', 'nigger', 'fuck', 'cunt', 'dick', 'tranny', 'fag', 'example', '123', 'sample', 'test', 'legal', 'contact'
|
||||||
|
];
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Personal settings would go after here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Proxy Server
|
||||||
|
!!!!!!!LIST!!!!!!!
|
||||||
|
|
||||||
|
168.8.209.253:8080
|
||||||
|
47.176.153.17:80
|
||||||
|
103.11.106.105:8181
|
||||||
|
157.245.83.157:80
|
||||||
|
54.200.36.47:80
|
||||||
|
*/
|
||||||
|
|
||||||
|
define( 'YOURLS_PROXY', '54.200.36.47:80' );
|
864
user/dark.css
Normal file
@ -0,0 +1,864 @@
|
|||||||
|
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800");
|
||||||
|
@import url("https://fonts.googleapis.com/icon?family=Material+Icons");
|
||||||
|
body {
|
||||||
|
background-color: #1d1d1d;
|
||||||
|
display: inline
|
||||||
|
}
|
||||||
|
|
||||||
|
div,
|
||||||
|
p,
|
||||||
|
td,
|
||||||
|
input,
|
||||||
|
p {
|
||||||
|
font-family: 'Open Sans', sans-serif !important
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
color: #ececec
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:link,
|
||||||
|
a:active,
|
||||||
|
a:visited {
|
||||||
|
color: #828282;
|
||||||
|
text-decoration: none
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #b9b9b9;
|
||||||
|
transition: 0.4s all
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 10px;
|
||||||
|
border: none !important;
|
||||||
|
background: #313131 !important;
|
||||||
|
color: #dcdcdc !important;
|
||||||
|
font-size: 1em !important;
|
||||||
|
outline: none;
|
||||||
|
margin: 0px 5px !important;
|
||||||
|
border-radius: 0 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button,
|
||||||
|
input.submit,
|
||||||
|
input[type="submit"] {
|
||||||
|
border-left: 7px solid #7289DA !important;
|
||||||
|
background: #313131 !important;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: 0.3s all !important;
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button:hover,
|
||||||
|
input.submit:hover,
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
background: #4E5D94 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="button"]:disabled,
|
||||||
|
input[type="submit"]:disabled {
|
||||||
|
cursor: not-allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text,
|
||||||
|
input[type="text"] {
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25) !important;
|
||||||
|
transition: 0.4s all
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text:active,
|
||||||
|
input.text:focus {
|
||||||
|
border: 1px solid #7289DA !important
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 150px;
|
||||||
|
padding: 5px 35px 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 26px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
color: #dcdcdc;
|
||||||
|
background: url(data:image/png;base64,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) 96%/15% no-repeat #313131;
|
||||||
|
margin: 5px 10px;
|
||||||
|
transition: 0.4s all;
|
||||||
|
outline: none
|
||||||
|
}
|
||||||
|
|
||||||
|
select:hover {
|
||||||
|
background: url(data:image/png;base64,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) 96%/15% no-repeat #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
#javascript_error {
|
||||||
|
background: red;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar {
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: none;
|
||||||
|
border: none;
|
||||||
|
opacity: 1;
|
||||||
|
box-shadow: none;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 500;
|
||||||
|
position: static;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: -45px;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar a,
|
||||||
|
.jquery-notify-bar a:link,
|
||||||
|
.jquery-notify-bar a:active,
|
||||||
|
.jquery-notify-bar a:visited {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar.error,
|
||||||
|
.jquery-notify-bar.fail {
|
||||||
|
background-color: #FF9800;
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar.success {
|
||||||
|
color: white;
|
||||||
|
background-color: #4CAF50
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #wrap {
|
||||||
|
margin: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.login label {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .login-logo {
|
||||||
|
width: 200px;
|
||||||
|
margin: 30px auto;
|
||||||
|
display: flex
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.text {
|
||||||
|
width: 270px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.button {
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 10px 25px;
|
||||||
|
margin-top: 15px !important;
|
||||||
|
font-weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.button else {
|
||||||
|
background: #313131 !important;
|
||||||
|
border-left: 7px solid #7289DA !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.button:hover {
|
||||||
|
background: #4E5D94 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .error {
|
||||||
|
padding: 10px;
|
||||||
|
background: #7289DA;
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #add-url {
|
||||||
|
width: 200px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url_form {
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url {
|
||||||
|
border: none;
|
||||||
|
background: #232323;
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url input.button {
|
||||||
|
margin-top: 10px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url div {
|
||||||
|
background: #232323;
|
||||||
|
padding: 4px;
|
||||||
|
padding-top: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .create {
|
||||||
|
background: #7289DA !important;
|
||||||
|
width: 150px;
|
||||||
|
font-size: 1.3em !important;
|
||||||
|
border: none !important;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px !important;
|
||||||
|
margin-left: 20px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 50px;
|
||||||
|
background: #232323
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top label {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top input.text {
|
||||||
|
width: 360px;
|
||||||
|
padding: 4px;
|
||||||
|
font-weight: 200;
|
||||||
|
font-size: 1em !important;
|
||||||
|
background: #464646 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top .short {
|
||||||
|
padding-left: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top #add-keyword {
|
||||||
|
width: 100px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top input.button {
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1em !important;
|
||||||
|
margin-left: 10px !important;
|
||||||
|
background: #464646 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top input.button:hover {
|
||||||
|
background: #4E5D94 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top #new_url_form {
|
||||||
|
margin-left: 260px;
|
||||||
|
padding: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter {
|
||||||
|
background-color: #232323;
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter a {
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter small a {
|
||||||
|
color: gray
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter thead tr .tablesorter-header {
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tfoot tr {
|
||||||
|
background-color: #232323
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter thead tr th,
|
||||||
|
.index table.tblSorter tfoot tr th,
|
||||||
|
.index table.tblSorter th.header {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 4px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter thead tr .tablesorter-headerAsc,
|
||||||
|
.index table.tblSorter thead tr .tablesorter-headerDesc {
|
||||||
|
background-color: #464646 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tbody td {
|
||||||
|
color: #dcdcdc;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #313131;
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: 0.4s all
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tbody tr:hover td {
|
||||||
|
background-color: #464646 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tbody tr.normal-row td {
|
||||||
|
background: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter .keyword {
|
||||||
|
border-left: 7px solid #7289DA
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter input.text {
|
||||||
|
padding: 5px;
|
||||||
|
margin: 8px 5px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter .navigation .nav_link a {
|
||||||
|
background: #313131;
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter .navigation .nav_link a:hover {
|
||||||
|
background: #464646
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tr.edit-row td {
|
||||||
|
background: #232323 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_stats {
|
||||||
|
background: #7289DA url(../img/stats.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_stats:hover {
|
||||||
|
background: #4E5D94 url(../img/stats.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_share {
|
||||||
|
background: #7289DA url(../img/share.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_share:hover {
|
||||||
|
background: #4E5D94 url(../img/share.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_edit {
|
||||||
|
background: #7289DA url(../img/edit.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_edit:hover {
|
||||||
|
background: #4E5D94 url(../img/edit.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_delete {
|
||||||
|
background: red url(../img/delete.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_delete:hover {
|
||||||
|
background: #c00 url(../img/delete.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
background: #232323;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 50px 30px;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
nav li#admin_menu_logout_link {
|
||||||
|
font-size: 1.3em
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul#admin_menu li:hover {
|
||||||
|
list-style-type: none;
|
||||||
|
color: #b9b9b9
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul#admin_menu li {
|
||||||
|
color: #ececec;
|
||||||
|
padding: 5px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
nav #admin_menu_logout_link:hover {
|
||||||
|
color: #ececec !important
|
||||||
|
}
|
||||||
|
|
||||||
|
nav .admin_menu_sublevel {
|
||||||
|
font-weight: 100;
|
||||||
|
margin-left: -20px
|
||||||
|
}
|
||||||
|
|
||||||
|
nav .material-icons {
|
||||||
|
font-size: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-top: -1px
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
list-style-type: none
|
||||||
|
}
|
||||||
|
|
||||||
|
img.logo {
|
||||||
|
width: 150px;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: #7289DA;
|
||||||
|
padding: 9px 90px 8px 20px;
|
||||||
|
z-index: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open {
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 30;
|
||||||
|
padding: 10px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open i {
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 30px
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs {
|
||||||
|
min-width: 580px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs .tab {
|
||||||
|
background: #313131 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs .wrap_unfloat {
|
||||||
|
margin-bottom: -5px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers {
|
||||||
|
border: none;
|
||||||
|
padding: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs li {
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs #historical_clicks li:hover {
|
||||||
|
background: #0a0a0a !important
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a,
|
||||||
|
#wrap #tabs #stats_lines li a {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background: #313131;
|
||||||
|
color: #dcdcdc;
|
||||||
|
padding: 10px 15px 7px 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a:hover,
|
||||||
|
#wrap #tabs #stats_lines li a:hover {
|
||||||
|
background: #0a0a0a
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a h2,
|
||||||
|
#wrap #tabs #stats_lines li a h2 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a.selected,
|
||||||
|
#wrap #tabs #stats_lines li a.selected {
|
||||||
|
background: #464646;
|
||||||
|
border-bottom: 2px solid #7289DA
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a.selected:hover,
|
||||||
|
#wrap #tabs #stats_lines li a.selected:hover {
|
||||||
|
background: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs #stats_lines li a {
|
||||||
|
padding: 7px 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul.toggle_display {
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs svg ellipse {
|
||||||
|
fill: #7289DA
|
||||||
|
}
|
||||||
|
|
||||||
|
body.index #wrap {
|
||||||
|
padding-top: 50px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap {
|
||||||
|
background: none;
|
||||||
|
margin-left: 270px;
|
||||||
|
border: none;
|
||||||
|
color: #dcdcdc;
|
||||||
|
max-width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
width: calc(100% - 22px);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: #7289DA;
|
||||||
|
border: 1px solid #7289DA;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice p {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
#shareboxes {
|
||||||
|
margin-top: -10px
|
||||||
|
}
|
||||||
|
|
||||||
|
#sharebox {
|
||||||
|
width: 558px;
|
||||||
|
margin-right: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share {
|
||||||
|
background: #232323;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
padding: 0px 20px 10px;
|
||||||
|
margin-top: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share textarea {
|
||||||
|
background: #313131;
|
||||||
|
color: #dcdcdc;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
outline: none;
|
||||||
|
margin: 1px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share #charcount {
|
||||||
|
padding-left: 5px;
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share #share_links a {
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap,
|
||||||
|
.plugins main,
|
||||||
|
.plugin_page_sleeky_settings main,
|
||||||
|
code {
|
||||||
|
background: #232323;
|
||||||
|
padding: 10px;
|
||||||
|
padding: 5px 25px;
|
||||||
|
max-width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap span,
|
||||||
|
.plugins main span,
|
||||||
|
.plugin_page_sleeky_settings main span,
|
||||||
|
code span {
|
||||||
|
background: rgba(255, 255, 255, 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap code,
|
||||||
|
.sub_wrap tt,
|
||||||
|
.plugins main code,
|
||||||
|
.plugins main tt,
|
||||||
|
.plugin_page_sleeky_settings main code,
|
||||||
|
.plugin_page_sleeky_settings main tt,
|
||||||
|
code code,
|
||||||
|
code tt {
|
||||||
|
background: rgba(0, 123, 255, 0.7)
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap a.bookmarklet,
|
||||||
|
.plugins main a.bookmarklet,
|
||||||
|
.plugin_page_sleeky_settings main a.bookmarklet,
|
||||||
|
code a.bookmarklet {
|
||||||
|
border: none;
|
||||||
|
background: #fff url(/images/favicon.gif) 4px center no-repeat;
|
||||||
|
color: #3c3c3c;
|
||||||
|
border-radius: 1px;
|
||||||
|
padding: 7px 7px 7px 25px;
|
||||||
|
color: #333 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap a.bookmarklet:hover,
|
||||||
|
.plugins main a.bookmarklet:hover,
|
||||||
|
.plugin_page_sleeky_settings main a.bookmarklet:hover,
|
||||||
|
code a.bookmarklet:hover {
|
||||||
|
background: #e0e0e0 url(/images/favicon.gif) 4px center no-repeat
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter,
|
||||||
|
.plugins main table.tblSorter,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter,
|
||||||
|
code table.tblSorter {
|
||||||
|
background: #232323
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter a,
|
||||||
|
.plugins main table.tblSorter a,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter a,
|
||||||
|
code table.tblSorter a {
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter a:hover,
|
||||||
|
.plugins main table.tblSorter a:hover,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter a:hover,
|
||||||
|
code table.tblSorter a:hover {
|
||||||
|
color: #909090
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter thead tr th,
|
||||||
|
.sub_wrap table.tblSorter tfoot tr th,
|
||||||
|
.sub_wrap table.tblSorter th.header,
|
||||||
|
.plugins main table.tblSorter thead tr th,
|
||||||
|
.plugins main table.tblSorter tfoot tr th,
|
||||||
|
.plugins main table.tblSorter th.header,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter thead tr th,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter tfoot tr th,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter th.header,
|
||||||
|
code table.tblSorter thead tr th,
|
||||||
|
code table.tblSorter tfoot tr th,
|
||||||
|
code table.tblSorter th.header {
|
||||||
|
border: none;
|
||||||
|
background-color: #313131;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter tbody td,
|
||||||
|
.plugins main table.tblSorter tbody td,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter tbody td,
|
||||||
|
code table.tblSorter tbody td {
|
||||||
|
background: #464646;
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
#filter_options {
|
||||||
|
padding: 0px 10px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
body>div>pre {
|
||||||
|
overflow-x: scroll;
|
||||||
|
padding-left: 290px
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 230px;
|
||||||
|
color: #828282;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer p {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer p a {
|
||||||
|
background: none;
|
||||||
|
padding-left: 0;
|
||||||
|
color: #dcdcdc
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer p a:hover {
|
||||||
|
color: #828282
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 899px) {
|
||||||
|
body.index #wrap {
|
||||||
|
padding-top: 210px
|
||||||
|
}
|
||||||
|
body.tools #wrap,
|
||||||
|
body.plugins #wrap,
|
||||||
|
body.plugin_page_sleeky_settings #wrap {
|
||||||
|
padding-top: 50px
|
||||||
|
}
|
||||||
|
#wrap {
|
||||||
|
margin-left: 0
|
||||||
|
}
|
||||||
|
#wrap main {
|
||||||
|
overflow-x: scroll
|
||||||
|
}
|
||||||
|
img.logo {
|
||||||
|
padding: 9px 100% 8px 20px
|
||||||
|
}
|
||||||
|
.nav-open {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
height: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 0
|
||||||
|
}
|
||||||
|
nav ul#admin_menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 50px;
|
||||||
|
display: none;
|
||||||
|
background: #232323
|
||||||
|
}
|
||||||
|
nav ul#admin_menu li {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
nav ul#admin_menu a,
|
||||||
|
nav ul#admin_menu a:link,
|
||||||
|
nav ul#admin_menu a:active,
|
||||||
|
nav ul#admin_menu a:visited {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
.index .top {
|
||||||
|
display: block;
|
||||||
|
margin-top: 50px;
|
||||||
|
width: 100vw;
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
.index .top form {
|
||||||
|
margin-left: 0 !important
|
||||||
|
}
|
||||||
|
.index .top #new_url_form {
|
||||||
|
min-width: unset;
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
.index .top .short {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
.index .top #add-url,
|
||||||
|
.index .top #add-keyword {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
margin: 10px 0px !important
|
||||||
|
}
|
||||||
|
.index .top input.button {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
.index table.tblSorter {
|
||||||
|
min-width: 600px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_stats {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_share {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_edit {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_delete {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
#copybox {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
.jquery-notify-bar {
|
||||||
|
margin-top: 210px;
|
||||||
|
margin-bottom: -210px;
|
||||||
|
width: calc(100vw - 20px)
|
||||||
|
}
|
||||||
|
.jquery-notify-bar a {
|
||||||
|
margin-left: -30px
|
||||||
|
}
|
||||||
|
#footer {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
.infos #wrap {
|
||||||
|
margin-top: 30px
|
||||||
|
}
|
||||||
|
.infos #wrap #headers li {
|
||||||
|
margin: 0;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
.infos #tabs {
|
||||||
|
min-width: initial
|
||||||
|
}
|
||||||
|
.infos #tabs .tab {
|
||||||
|
overflow: scroll
|
||||||
|
}
|
||||||
|
.infos #tabs ul#headers {
|
||||||
|
margin: 20px 0
|
||||||
|
}
|
||||||
|
.infos #tabs ul#headers li a {
|
||||||
|
padding: 10px 5px
|
||||||
|
}
|
||||||
|
.infos #tabs ul#headers li h2 {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
body>div>pre {
|
||||||
|
padding-left: 20px
|
||||||
|
}
|
||||||
|
}
|
22
user/dark.scss
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Sleeky Admin Dark UI Theme
|
||||||
|
|
||||||
|
// Define theme
|
||||||
|
$theme: "dark";
|
||||||
|
|
||||||
|
// Set up our basic colour scheme
|
||||||
|
$lightest: #464646;
|
||||||
|
$light: #313131;
|
||||||
|
$default: #232323;
|
||||||
|
$darker: #1d1d1d;
|
||||||
|
$darkest: #161616;
|
||||||
|
|
||||||
|
// Accents
|
||||||
|
$accent: #007bff;
|
||||||
|
// $accent_primary: #007bff;
|
||||||
|
|
||||||
|
// Text colours
|
||||||
|
$title: #ececec;
|
||||||
|
$text: #dcdcdc;
|
||||||
|
|
||||||
|
// Import the base styles
|
||||||
|
@import "../base.scss";
|
BIN
user/delete.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
user/edit.png
Normal file
After Width: | Height: | Size: 239 B |
1
user/emojis.txt
Normal file
BIN
user/favicon.ico
Normal file
After Width: | Height: | Size: 11 KiB |
10
user/form.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<div class="top" id="add">
|
||||||
|
<form id="new_url_form" action="javascript:add_link();" method="get">
|
||||||
|
<label>Link</label>
|
||||||
|
<input type="url" id="add-url" name="url" value="" class="text" placeholder="e.g. sleeky.flynntes.com" required>
|
||||||
|
<label class="short">Short URL</label>
|
||||||
|
<input type="text" id="add-keyword" name="keyword" value="" class="text" placeholder="e.g. theme">
|
||||||
|
<input type="hidden" id="nonce-add" name="nonce-add" value="">
|
||||||
|
<input type="button" id="add-button" name="add-button" value="Shorten" class="button" onclick="add_link();">
|
||||||
|
</form>
|
||||||
|
</div>
|
24
user/get_emojis.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* you can update the emoji list by changing the unicode link below
|
||||||
|
* then, visit your site's /user/plugins/yourls-emojis/util/get_emojis.php page to run the script
|
||||||
|
*
|
||||||
|
* most recent 13.1 https://www.unicode.org/emoji/charts/full-emoji-list.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( !defined( 'YOURLS_ABSPATH' ) ) die();
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
/*
|
||||||
|
* Last retrieved: April 11, 2021
|
||||||
|
*/
|
||||||
|
function get_emojis() {
|
||||||
|
$detect_emoji = Emoji\detect_emoji(file_get_contents('https://unicode.org/Public/emoji/13.1/emoji-test.txt'));
|
||||||
|
$file = fopen(__DIR__ . '/emojis.txt', 'w+');
|
||||||
|
|
||||||
|
if ( sizeof($detect_emoji) > 0 ) {
|
||||||
|
foreach ( $detect_emoji as $emoji ) {
|
||||||
|
fwrite($file, $emoji['emoji']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get_emojis();
|
674
user/gpl-3.0.txt
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
18
user/http_BL.sql
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS `httpBL_log` (
|
||||||
|
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||||
|
`action` varchar(9) NOT NULL,
|
||||||
|
`ip` varchar(255) NOT NULL,
|
||||||
|
`type` varchar(50) NOT NULL,
|
||||||
|
`threat` varchar(3) NOT NULL,
|
||||||
|
`activity` varchar(255) NOT NULL,
|
||||||
|
`page` varchar(255) NOT NULL,
|
||||||
|
`ua` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`timestamp`)
|
||||||
|
) ENGINE=INNODB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `httpBL_wl` (
|
||||||
|
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||||
|
`ip` varchar(255) NOT NULL,
|
||||||
|
`notes` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`timestamp`)
|
||||||
|
) ENGINE=INNODB DEFAULT CHARSET=latin1;
|
46
user/installed.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "steppinghat/emoji-detector",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"version_normalized": "1.1.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/SteppingHat/php-emoji-detector.git",
|
||||||
|
"reference": "d2301e9553795e1ac2f3f2638438b3808654c57f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/SteppingHat/php-emoji-detector/zipball/d2301e9553795e1ac2f3f2638438b3808654c57f",
|
||||||
|
"reference": "d2301e9553795e1ac2f3f2638438b3808654c57f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/phpunit-bridge": "^5.0@dev"
|
||||||
|
},
|
||||||
|
"time": "2021-03-18T06:03:22+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"SteppingHat\\EmojiDetector\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Javan Eskander",
|
||||||
|
"homepage": "https://javaneskander.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Detect and validate emoji in an input string",
|
||||||
|
"homepage": "https://github.com/steppinghat/emoji-detector"
|
||||||
|
}
|
||||||
|
]
|
872
user/light.css
Normal file
@ -0,0 +1,872 @@
|
|||||||
|
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800");
|
||||||
|
@import url("https://fonts.googleapis.com/icon?family=Material+Icons");
|
||||||
|
body {
|
||||||
|
background-color: #efefef;
|
||||||
|
display: inline
|
||||||
|
}
|
||||||
|
|
||||||
|
div,
|
||||||
|
p,
|
||||||
|
td,
|
||||||
|
input,
|
||||||
|
p {
|
||||||
|
font-family: 'Open Sans', sans-serif !important
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
color: #1d1d1d
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:link,
|
||||||
|
a:active,
|
||||||
|
a:visited {
|
||||||
|
color: #828282;
|
||||||
|
text-decoration: none
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #000;
|
||||||
|
transition: 0.4s all
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 10px;
|
||||||
|
border: none !important;
|
||||||
|
background: #fff !important;
|
||||||
|
color: #313131 !important;
|
||||||
|
font-size: 1em !important;
|
||||||
|
outline: none;
|
||||||
|
margin: 0px 5px !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border-radius: 3px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button,
|
||||||
|
input.submit,
|
||||||
|
input[type="submit"] {
|
||||||
|
border-left: 7px solid #007bff !important;
|
||||||
|
background: #fff !important;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: 0.3s all !important;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #007bff !important;
|
||||||
|
border-left: none !important;
|
||||||
|
color: white !important;
|
||||||
|
font-weight: 700
|
||||||
|
}
|
||||||
|
|
||||||
|
input.button:hover,
|
||||||
|
input.submit:hover,
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
background: #0056b3 !important;
|
||||||
|
background: #0056b3 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="button"]:disabled,
|
||||||
|
input[type="submit"]:disabled {
|
||||||
|
cursor: not-allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
input.text,
|
||||||
|
input[type="text"] {
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25) !important;
|
||||||
|
transition: 0.4s all
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 150px;
|
||||||
|
padding: 5px 35px 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 26px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
color: #313131;
|
||||||
|
background: url(data:image/png;base64,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) 96%/15% no-repeat #fff;
|
||||||
|
margin: 5px 10px;
|
||||||
|
transition: 0.4s all;
|
||||||
|
outline: none
|
||||||
|
}
|
||||||
|
|
||||||
|
select:hover {
|
||||||
|
background: url(data:image/png;base64,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) 96%/15% no-repeat #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
#javascript_error {
|
||||||
|
background: red;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar {
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: none;
|
||||||
|
border: none;
|
||||||
|
opacity: 1;
|
||||||
|
box-shadow: none;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 500;
|
||||||
|
position: static;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: -45px;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar a,
|
||||||
|
.jquery-notify-bar a:link,
|
||||||
|
.jquery-notify-bar a:active,
|
||||||
|
.jquery-notify-bar a:visited {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar.error,
|
||||||
|
.jquery-notify-bar.fail {
|
||||||
|
background-color: #FF9800;
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
.jquery-notify-bar.success {
|
||||||
|
color: white;
|
||||||
|
background-color: #4CAF50
|
||||||
|
}
|
||||||
|
|
||||||
|
.login #wrap {
|
||||||
|
margin: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.login label {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .login-logo {
|
||||||
|
width: 150px;
|
||||||
|
margin: 30px auto;
|
||||||
|
display: flex
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.text {
|
||||||
|
width: 270px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.button {
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 10px 25px;
|
||||||
|
margin-top: 15px !important;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #007bff !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.button else {
|
||||||
|
background: #fff !important;
|
||||||
|
border-left: 7px solid #007bff !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login input.button:hover {
|
||||||
|
background: #0062cc !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .error {
|
||||||
|
padding: 10px;
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #add-url {
|
||||||
|
width: 200px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url_form {
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url {
|
||||||
|
border: none;
|
||||||
|
background: #f7f7f7;
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url input.button {
|
||||||
|
margin-top: 10px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index #new_url div {
|
||||||
|
background: #f7f7f7;
|
||||||
|
padding: 4px;
|
||||||
|
padding-top: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .create {
|
||||||
|
background: #007bff !important;
|
||||||
|
width: 150px;
|
||||||
|
font-size: 1.3em !important;
|
||||||
|
border: none !important;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px !important;
|
||||||
|
margin-left: 20px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 50px;
|
||||||
|
background: #0062cc
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top label {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #313131;
|
||||||
|
color: #f7f7f7
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top input.text {
|
||||||
|
width: 360px;
|
||||||
|
padding: 4px;
|
||||||
|
font-weight: 200;
|
||||||
|
font-size: 1em !important;
|
||||||
|
background: #f7f7f7 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top .short {
|
||||||
|
padding-left: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top #add-keyword {
|
||||||
|
width: 100px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top input.button {
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1em !important;
|
||||||
|
margin-left: 10px !important;
|
||||||
|
background: #e8e8e8 !important;
|
||||||
|
background: #f7f7f7 !important;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #007bff !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top input.button:hover {
|
||||||
|
background: #0062cc !important;
|
||||||
|
background: #e6e6e6 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index .top #new_url_form {
|
||||||
|
margin-left: 260px;
|
||||||
|
padding: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter a {
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter small a {
|
||||||
|
color: gray
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter thead tr .tablesorter-header {
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tfoot tr {
|
||||||
|
background-color: #f7f7f7
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter thead tr th,
|
||||||
|
.index table.tblSorter tfoot tr th,
|
||||||
|
.index table.tblSorter th.header {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 4px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter thead tr .tablesorter-headerAsc,
|
||||||
|
.index table.tblSorter thead tr .tablesorter-headerDesc {
|
||||||
|
background-color: #e8e8e8 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tbody td {
|
||||||
|
color: #313131;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #fff;
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: 0.4s all
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tbody tr:hover td {
|
||||||
|
background-color: #e8e8e8 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tbody tr.normal-row td {
|
||||||
|
background: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter .keyword {
|
||||||
|
border-left: 7px solid #007bff
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter input.text {
|
||||||
|
padding: 5px;
|
||||||
|
margin: 8px 5px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter .navigation .nav_link a {
|
||||||
|
background: #fff;
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter .navigation .nav_link a:hover {
|
||||||
|
background: #e8e8e8
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter tr.edit-row td {
|
||||||
|
background: #f7f7f7 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_stats {
|
||||||
|
background: #007bff url(../img/stats.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_stats:hover {
|
||||||
|
background: #0062cc url(../img/stats.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_share {
|
||||||
|
background: #007bff url(../img/share.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_share:hover {
|
||||||
|
background: #0062cc url(../img/share.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_edit {
|
||||||
|
background: #007bff url(../img/edit.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_edit:hover {
|
||||||
|
background: #0062cc url(../img/edit.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_delete {
|
||||||
|
background: red url(../img/delete.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.index table.tblSorter td.actions .button_delete:hover {
|
||||||
|
background: #c00 url(../img/delete.png) 0px center no-repeat;
|
||||||
|
background-size: 23px;
|
||||||
|
background-position: center
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
background: #f7f7f7;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 50px 30px;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
nav li#admin_menu_logout_link {
|
||||||
|
font-size: 1.3em
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul#admin_menu li:hover {
|
||||||
|
list-style-type: none;
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul#admin_menu li {
|
||||||
|
color: #1d1d1d;
|
||||||
|
padding: 5px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
nav #admin_menu_logout_link:hover {
|
||||||
|
color: #1d1d1d !important
|
||||||
|
}
|
||||||
|
|
||||||
|
nav .admin_menu_sublevel {
|
||||||
|
font-weight: 100;
|
||||||
|
margin-left: -20px
|
||||||
|
}
|
||||||
|
|
||||||
|
nav .material-icons {
|
||||||
|
font-size: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-top: -1px
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
list-style-type: none
|
||||||
|
}
|
||||||
|
|
||||||
|
img.logo {
|
||||||
|
width: 90px;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: #007bff;
|
||||||
|
padding: 9px 150px 8px 20px;
|
||||||
|
z-index: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open {
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 30;
|
||||||
|
padding: 10px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-open i {
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 30px
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs {
|
||||||
|
min-width: 580px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs .tab {
|
||||||
|
background: #fff !important
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs .wrap_unfloat {
|
||||||
|
margin-bottom: -5px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers {
|
||||||
|
border: none;
|
||||||
|
padding: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs li {
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs #historical_clicks li:hover {
|
||||||
|
background: #dedede !important
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a,
|
||||||
|
#wrap #tabs #stats_lines li a {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background: #fff;
|
||||||
|
color: #313131;
|
||||||
|
padding: 10px 15px 7px 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a:hover,
|
||||||
|
#wrap #tabs #stats_lines li a:hover {
|
||||||
|
background: #dedede
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a h2,
|
||||||
|
#wrap #tabs #stats_lines li a h2 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a.selected,
|
||||||
|
#wrap #tabs #stats_lines li a.selected {
|
||||||
|
background: #e8e8e8;
|
||||||
|
border-bottom: 2px solid #007bff
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul#headers li a.selected:hover,
|
||||||
|
#wrap #tabs #stats_lines li a.selected:hover {
|
||||||
|
background: #d1d1d1
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs #stats_lines li a {
|
||||||
|
padding: 7px 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs ul.toggle_display {
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap #tabs svg ellipse {
|
||||||
|
fill: #007bff
|
||||||
|
}
|
||||||
|
|
||||||
|
body.index #wrap {
|
||||||
|
padding-top: 50px
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrap {
|
||||||
|
background: none;
|
||||||
|
margin-left: 270px;
|
||||||
|
border: none;
|
||||||
|
color: #313131;
|
||||||
|
max-width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
width: calc(100% - 22px);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: #007bff;
|
||||||
|
border: 1px solid #007bff;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice p {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
|
||||||
|
#shareboxes {
|
||||||
|
margin-top: -10px
|
||||||
|
}
|
||||||
|
|
||||||
|
#sharebox {
|
||||||
|
width: 558px;
|
||||||
|
margin-right: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share {
|
||||||
|
background: #f7f7f7;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
padding: 0px 20px 10px;
|
||||||
|
margin-top: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share textarea {
|
||||||
|
background: #fff;
|
||||||
|
color: #313131;
|
||||||
|
border: none;
|
||||||
|
padding: 3px;
|
||||||
|
outline: none;
|
||||||
|
margin: 1px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share #charcount {
|
||||||
|
padding-left: 5px;
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
div.share #share_links a {
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap,
|
||||||
|
.plugins main,
|
||||||
|
.plugin_page_sleeky_settings main,
|
||||||
|
code {
|
||||||
|
background: #f7f7f7;
|
||||||
|
padding: 10px;
|
||||||
|
padding: 5px 25px;
|
||||||
|
max-width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap span,
|
||||||
|
.plugins main span,
|
||||||
|
.plugin_page_sleeky_settings main span,
|
||||||
|
code span {
|
||||||
|
background: rgba(255, 255, 255, 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap code,
|
||||||
|
.sub_wrap tt,
|
||||||
|
.plugins main code,
|
||||||
|
.plugins main tt,
|
||||||
|
.plugin_page_sleeky_settings main code,
|
||||||
|
.plugin_page_sleeky_settings main tt,
|
||||||
|
code code,
|
||||||
|
code tt {
|
||||||
|
background: rgba(0, 123, 255, 0.7);
|
||||||
|
background: rgba(35, 185, 222, 0.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap a.bookmarklet,
|
||||||
|
.plugins main a.bookmarklet,
|
||||||
|
.plugin_page_sleeky_settings main a.bookmarklet,
|
||||||
|
code a.bookmarklet {
|
||||||
|
border: none;
|
||||||
|
background: #fff url(/images/favicon.gif) 4px center no-repeat;
|
||||||
|
color: #3c3c3c;
|
||||||
|
border-radius: 1px;
|
||||||
|
padding: 7px 7px 7px 25px;
|
||||||
|
color: #333 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap a.bookmarklet:hover,
|
||||||
|
.plugins main a.bookmarklet:hover,
|
||||||
|
.plugin_page_sleeky_settings main a.bookmarklet:hover,
|
||||||
|
code a.bookmarklet:hover {
|
||||||
|
background: #e0e0e0 url(/images/favicon.gif) 4px center no-repeat
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter,
|
||||||
|
.plugins main table.tblSorter,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter,
|
||||||
|
code table.tblSorter {
|
||||||
|
background: #f7f7f7
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter a,
|
||||||
|
.plugins main table.tblSorter a,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter a,
|
||||||
|
code table.tblSorter a {
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter a:hover,
|
||||||
|
.plugins main table.tblSorter a:hover,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter a:hover,
|
||||||
|
code table.tblSorter a:hover {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter thead tr th,
|
||||||
|
.sub_wrap table.tblSorter tfoot tr th,
|
||||||
|
.sub_wrap table.tblSorter th.header,
|
||||||
|
.plugins main table.tblSorter thead tr th,
|
||||||
|
.plugins main table.tblSorter tfoot tr th,
|
||||||
|
.plugins main table.tblSorter th.header,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter thead tr th,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter tfoot tr th,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter th.header,
|
||||||
|
code table.tblSorter thead tr th,
|
||||||
|
code table.tblSorter tfoot tr th,
|
||||||
|
code table.tblSorter th.header {
|
||||||
|
border: none;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_wrap table.tblSorter tbody td,
|
||||||
|
.plugins main table.tblSorter tbody td,
|
||||||
|
.plugin_page_sleeky_settings main table.tblSorter tbody td,
|
||||||
|
code table.tblSorter tbody td {
|
||||||
|
background: #e8e8e8;
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
#filter_options {
|
||||||
|
padding: 0px 10px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
body>div>pre {
|
||||||
|
overflow-x: scroll;
|
||||||
|
padding-left: 290px
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 230px;
|
||||||
|
color: #828282;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer p {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer p a {
|
||||||
|
background: none;
|
||||||
|
padding-left: 0;
|
||||||
|
color: #313131
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer p a:hover {
|
||||||
|
color: #828282
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 899px) {
|
||||||
|
body.index #wrap {
|
||||||
|
padding-top: 210px
|
||||||
|
}
|
||||||
|
body.tools #wrap,
|
||||||
|
body.plugins #wrap,
|
||||||
|
body.plugin_page_sleeky_settings #wrap {
|
||||||
|
padding-top: 50px
|
||||||
|
}
|
||||||
|
#wrap {
|
||||||
|
margin-left: 0
|
||||||
|
}
|
||||||
|
#wrap main {
|
||||||
|
overflow-x: scroll
|
||||||
|
}
|
||||||
|
img.logo {
|
||||||
|
padding: 9px 100% 8px 20px
|
||||||
|
}
|
||||||
|
.nav-open {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
height: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 0
|
||||||
|
}
|
||||||
|
nav ul#admin_menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 50px;
|
||||||
|
display: none;
|
||||||
|
background: #0062cc
|
||||||
|
}
|
||||||
|
nav ul#admin_menu li {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
nav ul#admin_menu a,
|
||||||
|
nav ul#admin_menu a:link,
|
||||||
|
nav ul#admin_menu a:active,
|
||||||
|
nav ul#admin_menu a:visited {
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
.index .top {
|
||||||
|
display: block;
|
||||||
|
margin-top: 50px;
|
||||||
|
width: 100vw;
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
.index .top form {
|
||||||
|
margin-left: 0 !important
|
||||||
|
}
|
||||||
|
.index .top #new_url_form {
|
||||||
|
min-width: unset;
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
.index .top .short {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
.index .top #add-url,
|
||||||
|
.index .top #add-keyword {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
margin: 10px 0px !important
|
||||||
|
}
|
||||||
|
.index .top input.button {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
.index table.tblSorter {
|
||||||
|
min-width: 600px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_stats {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_share {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_edit {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
.index table.tblSorter td.actions .button_delete {
|
||||||
|
background-size: 15px;
|
||||||
|
margin: 3px
|
||||||
|
}
|
||||||
|
#copybox {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
.jquery-notify-bar {
|
||||||
|
margin-top: 210px;
|
||||||
|
margin-bottom: -210px;
|
||||||
|
width: calc(100vw - 20px)
|
||||||
|
}
|
||||||
|
.jquery-notify-bar a {
|
||||||
|
margin-left: -30px
|
||||||
|
}
|
||||||
|
#footer {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
.infos #wrap {
|
||||||
|
margin-top: 30px
|
||||||
|
}
|
||||||
|
.infos #wrap #headers li {
|
||||||
|
margin: 0;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
.infos #tabs {
|
||||||
|
min-width: initial
|
||||||
|
}
|
||||||
|
.infos #tabs .tab {
|
||||||
|
overflow: scroll
|
||||||
|
}
|
||||||
|
.infos #tabs ul#headers {
|
||||||
|
margin: 20px 0
|
||||||
|
}
|
||||||
|
.infos #tabs ul#headers li a {
|
||||||
|
padding: 10px 5px
|
||||||
|
}
|
||||||
|
.infos #tabs ul#headers li h2 {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
body>div>pre {
|
||||||
|
padding-left: 20px
|
||||||
|
}
|
||||||
|
}
|
22
user/light.scss
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Sleeky Admin Light UI Theme
|
||||||
|
|
||||||
|
// Define theme
|
||||||
|
$theme: "light";
|
||||||
|
|
||||||
|
// Set up our basic colour scheme
|
||||||
|
$lightest: #e8e8e8;
|
||||||
|
$light: white;
|
||||||
|
$default: #f7f7f7;
|
||||||
|
$darker: #efefef;
|
||||||
|
$darkest: #161616;
|
||||||
|
|
||||||
|
// Accents
|
||||||
|
$accent: #007bff;
|
||||||
|
// $accent_secondary: black;
|
||||||
|
|
||||||
|
// Text colours
|
||||||
|
$title: #1d1d1d;
|
||||||
|
$text: #313131;
|
||||||
|
|
||||||
|
// Import the base styles
|
||||||
|
@import "../base.scss";
|
BIN
user/logo_black.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
user/logo_black.webp
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
user/logo_white.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
user/logo_white.webp
Normal file
After Width: | Height: | Size: 13 KiB |
141
user/ludo_blacklist_ip_Check_IP_Module.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
function ludo_blacklist_ip_Analyze_IP ( $Input ) {
|
||||||
|
if ( strpos ( $Input , "/" ) !== FALSE ) { // Case input contain "/"
|
||||||
|
$Inputs = array_map ("trim", explode ( "/" , $Input ) );
|
||||||
|
if (ludo_blacklist_ip_Check_IP ( $Inputs[0] ) && ctype_digit ($Inputs[1]) && $Inputs[1] > 0 && $Inputs[1] <= 32) { // Cas CIDR
|
||||||
|
$Cible = ludo_blacklist_ip_CalculIPMask ( $Inputs[0] , ludo_blacklist_ip_MaskType2Mask ( $Inputs[1] ) ) ;
|
||||||
|
} elseif (ludo_blacklist_ip_Check_IP ( $Inputs[0] ) && ludo_blacklist_ip_Check_IP ($Inputs[1]) && ludo_blacklist_ip_Check_Mask ($Inputs[1]) ){ // Case IP/Mask
|
||||||
|
$Cible = ludo_blacklist_ip_CalculIPMask ( $Inputs[0] , $Inputs[1] ) ;
|
||||||
|
} else { // Contains "/" but invalid
|
||||||
|
$Cible="NULL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ( strpos ( $Input , "-" ) !== FALSE ) { // Case input contains "-"
|
||||||
|
$Inputs = array_map ("trim", explode ( "-" , $Input ) );
|
||||||
|
if ( ludo_blacklist_ip_Check_IP ( $Inputs[0] ) && ludo_blacklist_ip_Check_IP ( $Inputs[1] ) ) {
|
||||||
|
if ( $Inputs[0] < $Inputs[1] ) { // Check IP orders
|
||||||
|
$Cible = $Inputs[0] . "-" . $Inputs[1] ;
|
||||||
|
}
|
||||||
|
else { // If wrong order, reverse it
|
||||||
|
$Cible = $Inputs[1] . "-" . $Inputs[0] ;
|
||||||
|
}
|
||||||
|
} else { // Contains "-" but invalid
|
||||||
|
$Cible="NULL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (ludo_blacklist_ip_Check_IP ( $Input )) { // Case input is a single IP
|
||||||
|
$Inputs = array_map ("trim", explode ( "." , $Input ) );
|
||||||
|
if ( $Inputs[0] == 0 && $Inputs[1] == 0 && $Inputs[2] == 0 && $Inputs[3] == 0 ) { // Case 0.0.0.0
|
||||||
|
$Cible = "0.0.0.0-255.255.255.255" ;
|
||||||
|
}
|
||||||
|
elseif ( $Inputs[1] == 0 && $Inputs[2] == 0 && $Inputs[3] == 0 ) { // Case A.0.0.0
|
||||||
|
$Cible = $Inputs[0] . ".0.0.0-" . $Inputs[0] . ".255.255.255";
|
||||||
|
}
|
||||||
|
elseif ( $Inputs[2] == 0 && $Inputs[3] == 0 ) { // Case A.B.0.0
|
||||||
|
$Cible = $Inputs[0] . "." . $Inputs[1] . ".0.0-" . $Inputs[0] . "." . $Inputs[1] . ".255.255";
|
||||||
|
}
|
||||||
|
elseif ( $Inputs[3] == 0 ) { // Case A.B.C.0
|
||||||
|
$Cible = $Inputs[0] . "." . $Inputs[1] . "." . $Inputs[2] . ".0-" . $Inputs[0] . "." . $Inputs[1] . "." . $Inputs[2] . ".255";
|
||||||
|
}
|
||||||
|
else { // Case of a single IP address
|
||||||
|
$Cible = $Input . "-" . $Input ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // Invalid IP address
|
||||||
|
$Cible="NULL";
|
||||||
|
}
|
||||||
|
return $Cible;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ludo_blacklist_ip_Check_IP ( &$IP ) {
|
||||||
|
// Input : String of IP address
|
||||||
|
// Output : TRUE if string is a valid IP address
|
||||||
|
$IPs = array_map("ludo_blacklist_ip_IP_trim", explode ( "." , $IP ) ) ;
|
||||||
|
if (count ($IPs) != 4 ) return false ;
|
||||||
|
foreach ( $IPs as $value ) {
|
||||||
|
if ( $value < 0 || $value > 255 ) {
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$IP = implode ( ".", $IPs );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ludo_blacklist_ip_IP_Trim ( $IP ) {
|
||||||
|
// Input : array of IP address with strings
|
||||||
|
// Output : array of the IP address with integer
|
||||||
|
return (int) ltrim ( trim ( $IP ) , "0" ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ludo_blacklist_ip_Check_Mask ( $Mask ) {
|
||||||
|
// Input : Mask to be checked, string
|
||||||
|
// Return OK if the Mask string is correct
|
||||||
|
$Masks = array_map("ludo_blacklist_ip_IP_trim", explode ( "." , $Mask ) ) ;
|
||||||
|
if (count ($Masks) != 4 ) return false ;
|
||||||
|
$OctetSignificatif = -1;
|
||||||
|
foreach ( $Masks as $key => $value ) {
|
||||||
|
if ( $value == 255 and $OctetSignificatif == -1 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( $value == 255 and $OctetSignificatif != -1 ) {
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if ( $value >0 and $OctetSignificatif == -1 ) {
|
||||||
|
$OctetSignificatif = $key ;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( $value >0 and $OctetSignificatif != -1 ) {
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if ( $value == 0 and $OctetSignificatif == -1 and $Masks[$key-1] != 255) {
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if ( $value == 0 and $OctetSignificatif == -1 and $Masks[$key-1] == 255) {
|
||||||
|
$OctetSignificatif = $key;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
if ( $value == 0 and $OctetSignificatif != -1 ) {
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (($OctetSignificatif != -1) and in_array ($Masks[$OctetSignificatif],array ("255","254","252","248","240","224","192","128","0")));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ludo_blacklist_ip_MaskType2Mask ( $MaskType ) {
|
||||||
|
// Input : Integer value
|
||||||
|
// Output : Mask with $MaskType bit at 1, others at 0, string
|
||||||
|
for ($boucle = 0; $boucle < 4 ; $boucle++ ) {
|
||||||
|
if ( $MaskType > 8 ) $Masks[$boucle] = 255;
|
||||||
|
elseif ($MaskType <= 0 ) $Masks[$boucle] = 0;
|
||||||
|
else $Masks[$boucle] = bindec (str_repeat ( "1" , $MaskType ) . str_repeat ("0" , 8-$MaskType ) );
|
||||||
|
$MaskType -= 8;
|
||||||
|
}
|
||||||
|
return implode ( "." , $Masks);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ludo_blacklist_ip_CalculIPMask ( $IP , $Mask ) {
|
||||||
|
// Input : IP address and Mask, strings
|
||||||
|
// Output a string $IPStart."-".$IPEnd for those IP and mask
|
||||||
|
$IPs = explode ( "." , $IP ) ;
|
||||||
|
$Masks = explode ( "." , $Mask ) ;
|
||||||
|
$OctetSignificatif = -1;
|
||||||
|
|
||||||
|
for ($boucle = 0 ; $boucle < sizeof ( $IPs ) ; $boucle++ ) {
|
||||||
|
$IP_Starts[$boucle] = (0+$IPs[$boucle]) & (0+$Masks[$boucle]) ;
|
||||||
|
if (($Masks[$boucle] < 255) && ( $OctetSignificatif == -1 ) ) {
|
||||||
|
$OctetSignificatif = $boucle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ($boucle = 0 ; $boucle < sizeof ( $IPs ) ; $boucle++ ) {
|
||||||
|
if ($boucle < $OctetSignificatif )
|
||||||
|
$IP_Ends[$boucle] = 0+$IPs[$boucle] ;
|
||||||
|
elseif ($boucle == $OctetSignificatif )
|
||||||
|
$IP_Ends[$boucle] = (0+$IPs[$boucle]) | ( 255-$Masks[$boucle] ) ;
|
||||||
|
else
|
||||||
|
$IP_Ends[$boucle] = 255;
|
||||||
|
}
|
||||||
|
return implode ( "." , $IP_Starts)."-".implode ( "." , $IP_Ends);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
1
user/map.json
Normal file
BIN
user/no-entry.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
1293
user/package-lock.json
generated
Normal file
15
user/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "sleeky-admin",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "node-sass --watch assets/css/themes -o assets/css --output-style compressed"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"node-sass": "^4.12.0"
|
||||||
|
}
|
||||||
|
}
|
36
user/php.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: PHP Composer
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Validate composer.json and composer.lock
|
||||||
|
run: composer validate --strict
|
||||||
|
|
||||||
|
- name: Cache Composer packages
|
||||||
|
id: composer-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: vendor
|
||||||
|
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-php-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
|
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
|
||||||
|
# Docs: https://getcomposer.org/doc/articles/scripts.md
|
||||||
|
|
||||||
|
# - name: Run test suite
|
||||||
|
# run: composer run-script test
|
29
user/phpunit.xml.dist
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<phpunit backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="EmojiDetector">
|
||||||
|
<directory>./test/</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<php>
|
||||||
|
<ini name="error_reporting" value="-1" />
|
||||||
|
<ini name="xdebug.overload_var_dump" value="0" />
|
||||||
|
</php>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory suffix=".php">./src/</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
72
user/plugin.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
Plugin Name: YouTube Title Fix
|
||||||
|
Plugin URI: https://github.com/joshp23/YOURLS-YouTube-title-fix
|
||||||
|
Description: Fetch YouTube Titles via Google API
|
||||||
|
Version: 2.0.0
|
||||||
|
Author: Josh Panter
|
||||||
|
Author URI: https://unfettered.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
// No direct call
|
||||||
|
if( !defined( 'YOURLS_ABSPATH' ) ) die();
|
||||||
|
// Add the admin page
|
||||||
|
yourls_add_action( 'plugins_loaded', 'youtube_title_fix_add_page' );
|
||||||
|
|
||||||
|
function youtube_title_fix_add_page() {
|
||||||
|
yourls_register_plugin_page( 'youtube_title_fix', 'YouTube API', 'youtube_title_fix_do_page' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display admin page
|
||||||
|
function youtube_title_fix_do_page() {
|
||||||
|
|
||||||
|
if( isset( $_POST['youtube_title_fix_api_key'] ) ) {
|
||||||
|
yourls_verify_nonce( 'youtube_title_fix' );
|
||||||
|
yourls_update_option( 'youtube_title_fix_api_key', $_POST['youtube_title_fix_api_key'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
$youtube_title_fix_api_key = yourls_get_option( 'youtube_title_fix_api_key' );
|
||||||
|
$nonce = yourls_create_nonce( 'youtube_title_fix' );
|
||||||
|
|
||||||
|
echo <<<HTML
|
||||||
|
<div id="wrap">
|
||||||
|
<h2>YouTube API Key</h2>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="nonce" value="$nonce" />
|
||||||
|
<p><label for="youtube_title_fix_api_key">Your Key </label> <input type="text" size=60 id="youtube_title_fix_api_key" name="youtube_title_fix_api_key" value="$youtube_title_fix_api_key" /></p>
|
||||||
|
|
||||||
|
<p><input type="submit" value="Submit" /></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
yourls_add_filter( 'shunt_get_remote_title', 'youtube_title_fix_get_remote_title' );
|
||||||
|
function youtube_title_fix_get_remote_title( $return , $url ) {
|
||||||
|
|
||||||
|
$url = yourls_sanitize_url( $url );
|
||||||
|
|
||||||
|
// only deal with http(s)
|
||||||
|
if ( !in_array( yourls_get_protocol( $url ), array( 'http://', 'https://' ) ) )
|
||||||
|
return 'PROTOCOL';
|
||||||
|
|
||||||
|
// parse url and check host + querry string
|
||||||
|
$parsed_url = parse_url( $url );
|
||||||
|
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
|
||||||
|
$query = isset($parsed_url['query']) ? $parsed_url['query'] : '';
|
||||||
|
parse_str( $query , $array );
|
||||||
|
|
||||||
|
if ( preg_match( '/(youtube|youtu\.be)/', $host ) && isset( $array['v'] ) ) {
|
||||||
|
// we need an API key
|
||||||
|
$API_KEY = yourls_get_option( 'youtube_title_fix_api_key' );
|
||||||
|
if( $API_KEY ) {
|
||||||
|
$vid = $array['v'];
|
||||||
|
$data = json_decode( file_get_contents( "https://www.googleapis.com/youtube/v3/videos?part=snippet&id=" . $vid ."&key=" . $API_KEY ) );
|
||||||
|
$title = $data->items[0]->snippet->title;
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
1
user/raw.json
Normal file
22
user/readme.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Plugin for YOURLS 1.7+: Google Safe Browsing
|
||||||
|
|
||||||
|
# What for
|
||||||
|
|
||||||
|
Check every new URL against Google's Safe Browsing Lookup service, reject those who are identified as malware or phishing
|
||||||
|
|
||||||
|
# How to
|
||||||
|
|
||||||
|
* In `/user/plugins`, create a new folder named `google-safe-browsing`
|
||||||
|
* Drop these files in that directory
|
||||||
|
* Go to the Plugins administration page and activate the plugin
|
||||||
|
* Follow on-screen instructions
|
||||||
|
* Have fun
|
||||||
|
|
||||||
|
# Disclaimer
|
||||||
|
|
||||||
|
Using this plugin requires you to understand Google's Safe Browsing TOS. In short:
|
||||||
|
* you need a Google account
|
||||||
|
* you are limited to a certain amount of queries per day (10,000 as of writing this)
|
||||||
|
* you must understand that the service is not perfect.
|
||||||
|
|
||||||
|
[Read more](https://developers.google.com/safe-browsing/lookup_guide#AcceptableUsage)
|
BIN
user/share.png
Normal file
After Width: | Height: | Size: 496 B |
BIN
user/stats.png
Normal file
After Width: | Height: | Size: 243 B |
36
user/tests.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'plugin.php';
|
||||||
|
|
||||||
|
function yourls_add_filter($a, $b) { }
|
||||||
|
|
||||||
|
$fixture = array();
|
||||||
|
$fixture[] = array('127.0.0.1' => '127.0.0.0');
|
||||||
|
$fixture[] = array('192.0.43.10' => '192.0.43.0'); // example.com
|
||||||
|
$fixture[] = array('::1' => '::0');
|
||||||
|
$fixture[] = array('::ffff:127.0.0.1' => '::ffff:127.0.0.0');
|
||||||
|
$fixture[] = array('::ffff:192.0.43.10' => '::ffff:192.0.43.0');
|
||||||
|
$fixture[] = array('2001:0db8:85a3:0000:0000:8a2e:0370:7334' => '2001:0db8:85a3:0000:0000:8a2e:0370:0');
|
||||||
|
|
||||||
|
|
||||||
|
$success = TRUE;
|
||||||
|
echo "Running tests...\n";
|
||||||
|
|
||||||
|
for ($i = 0; $i <= count($fixture)-1; $i++) {
|
||||||
|
foreach ($fixture[$i] as $actual => $expected) {
|
||||||
|
$success &= assertEquals($expected, ubicoo_pseudonymize_IP( $actual ), $actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Tests " . ($success ? "succeeded" : "failed") .".\n";
|
||||||
|
|
||||||
|
|
||||||
|
function assertEquals($expected, $actualAfter, $actualBefore)
|
||||||
|
{
|
||||||
|
echo " Checking $actualBefore => $expected ? ... ";
|
||||||
|
if ($actualAfter !== $expected) {
|
||||||
|
echo "FAILED - was $actualAfter\n";
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
echo "OK\n";
|
||||||
|
return TRUE;
|
||||||
|
}
|
141
user/theme.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
console.log("SOP Proprietary v1.9");
|
||||||
|
|
||||||
|
$( document ).ready(function() {
|
||||||
|
// Get the theme URL
|
||||||
|
var url;
|
||||||
|
if ($('meta[name=pluginURL]').attr("content")) {
|
||||||
|
url = $('meta[name=pluginURL]').attr("content");
|
||||||
|
} else {
|
||||||
|
// If for some reason we can't find the URL attribute
|
||||||
|
url = "/user/plugins/backend";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect theme
|
||||||
|
var theme;
|
||||||
|
if ($('meta[name=sleeky_theme]').attr("content") == 'light') {
|
||||||
|
theme = "light";
|
||||||
|
} else if ($('meta[name=sleeky_theme]').attr("content") == 'dark') {
|
||||||
|
theme = "dark";
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Theme is", theme)
|
||||||
|
|
||||||
|
// Update favicon
|
||||||
|
$('link[rel="shortcut icon"]').attr('href', url + "/images/favicon.ico");
|
||||||
|
|
||||||
|
// Update meta viewport
|
||||||
|
$('head').append('<meta name="viewport" content="width=device-width, initial-scale=1.0">');
|
||||||
|
|
||||||
|
// Detect pages
|
||||||
|
if ($("body").hasClass("login")) {
|
||||||
|
// Login page
|
||||||
|
console.log("Login page");
|
||||||
|
|
||||||
|
if (theme == "light") {
|
||||||
|
$("#login").prepend(`<img class="login-logo" src="${url}/assets/img/logo_black.png">`);
|
||||||
|
} else if (theme == "dark") {
|
||||||
|
$("#login").prepend(`<img class="login-logo" src="${url}/assets/img/logo_white.png">`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if ($("body").hasClass("index")) {
|
||||||
|
// Index page
|
||||||
|
console.log("Index page");
|
||||||
|
|
||||||
|
handleNav()
|
||||||
|
|
||||||
|
// Hide YOURLS new URL section
|
||||||
|
$("#new_url").hide();
|
||||||
|
|
||||||
|
// Grab the nonce id
|
||||||
|
var nonce = $("#nonce-add").val();
|
||||||
|
|
||||||
|
// Remove the YOURLS new URL Section
|
||||||
|
$("#new_url").remove();
|
||||||
|
|
||||||
|
// Create the sleeky new URL section from the template
|
||||||
|
$("nav").append($('<div>').load(`${url}/assets/html/form.html`, function () {
|
||||||
|
$("#nonce-add").val(nonce);
|
||||||
|
}));
|
||||||
|
} else if ($("body").hasClass("tools")) {
|
||||||
|
// Tools page
|
||||||
|
console.log("Tools page");
|
||||||
|
|
||||||
|
handleNav()
|
||||||
|
|
||||||
|
} else if ($("body").hasClass("plugins")) {
|
||||||
|
// Plugins page
|
||||||
|
console.log("Plugins page");
|
||||||
|
|
||||||
|
handleNav()
|
||||||
|
|
||||||
|
} else if ($("body").hasClass("plugin_page_sleeky_settings")) {
|
||||||
|
// Tools page
|
||||||
|
console.log("Sleeky Settings Page");
|
||||||
|
|
||||||
|
handleNav()
|
||||||
|
|
||||||
|
$("#ui_selector").val($("#ui_selector").attr("value"));
|
||||||
|
|
||||||
|
} else if ($("body").hasClass("infos")) {
|
||||||
|
// Information page
|
||||||
|
console.log("Information page");
|
||||||
|
|
||||||
|
handleNav()
|
||||||
|
|
||||||
|
$("#historical_clicks li").each(function (index) {
|
||||||
|
if (index % 2 != 0) {
|
||||||
|
$("#historical_clicks li").eq(index).css("background", "");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update tab headers
|
||||||
|
var titles = ['Statistics', 'Location', 'Sources']
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
$($('#headers > li')[i]).find('h2').text(titles[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Unknown page");
|
||||||
|
|
||||||
|
handleNav();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleNav() {
|
||||||
|
// Add logo
|
||||||
|
$("#wrap").prepend(`<img class="logo" src="${url}/assets/img/logo_white.png">`);
|
||||||
|
|
||||||
|
// Add mobile nav hamburger
|
||||||
|
$("#wrap").prepend(`<div class="nav-open" id="navOpen"><i class="material-icons">menu</i></div>`);
|
||||||
|
|
||||||
|
// Add frontend link
|
||||||
|
$('#admin_menu').append('<li class="admin_menu_toplevel frontend_link"><a href="/"><i class="material-icons">arrow_back</i> Frontend Interface</a></li>');
|
||||||
|
|
||||||
|
// admin_menu
|
||||||
|
$('#navOpen').on('click', function() {
|
||||||
|
$('#admin_menu').slideToggle();
|
||||||
|
})
|
||||||
|
|
||||||
|
$(window).resize(function () {
|
||||||
|
if ($(window).width() > 899) {
|
||||||
|
$('#admin_menu').show();
|
||||||
|
} else {
|
||||||
|
$('#admin_menu').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update P elements
|
||||||
|
$("p").each(function (index) {
|
||||||
|
if (/Display/.test($(this).text()) || /Overall/.test($(this).text())) {
|
||||||
|
// Move info on index page to the bottom
|
||||||
|
$("main").append("<p>" + $(this).html() + "</p>");
|
||||||
|
$(this).remove();
|
||||||
|
} else if (/Powered by/.test($(this).text())) {
|
||||||
|
// Update footer
|
||||||
|
var content = $(this).html();
|
||||||
|
var i = 77
|
||||||
|
var updated_content = 'Running <a href="https://sop.wtf/YOURLS">YOURLS</a> &' + ' <a href="https://sop.wtf/darksleeky">Dark Sleeky</a>' + content.slice(i-1)
|
||||||
|
$(this).html(updated_content);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|