Upload files to 'user'
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: telepathics
|
|
@ -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.
|
|
@ -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.
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
PHP Emoji Detector
|
||||
==================
|
||||
|
||||
[![Latest Stable Version](https://poser.pugx.org/steppinghat/emoji-detector/v)](//packagist.org/packages/steppinghat/emoji-detector) [![Total Downloads](https://poser.pugx.org/steppinghat/emoji-detector/downloads)](//packagist.org/packages/steppinghat/emoji-detector) [![License](https://poser.pugx.org/steppinghat/emoji-detector/license)](//packagist.org/packages/steppinghat/emoji-detector) [![Build Status](https://travis-ci.com/SteppingHat/php-emoji-detector.svg?branch=master)](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)
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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' ) );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInitb527cf0f410cc8001ea07d072eb1427c::getLoader();
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
|
@ -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'),
|
||||
);
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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 );
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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' );
|
|
@ -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,iVBORw0KGgoAAAANSUhEUgAAABkAAAAeCAYAAADZ7LXbAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAKRJREFUeNrs1TEKwkAQheEvIoI2nsk7qFdIq1hoJ3gCC5sUVpY23sDKXnvrYOUBbGITG0kQjQriPlgYhmF/3ryFjbIs82nVfEEBEiAB8k+Q+q1IkqSDNVq4lMy3scIkjuP0FSdbjNHMLys6OwyQVlnXEsOS2QP6OL8jkzlmd70jus86eBT8FIu8PqGXg6oFX6ARGthgX+V1ReFnDJAACZAfhFwHAJI7HF2lZGQaAAAAAElFTkSuQmCC) 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
|
||||
}
|
||||
}
|
|
@ -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";
|
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 239 B |
After Width: | Height: | Size: 11 KiB |
|
@ -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>
|
|
@ -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();
|
|
@ -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>.
|
|
@ -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;
|
|
@ -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"
|
||||
}
|
||||
]
|
|
@ -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,iVBORw0KGgoAAAANSUhEUgAAABkAAAAeCAYAAADZ7LXbAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAKRJREFUeNrs1TEKwkAQheEvIoI2nsk7qFdIq1hoJ3gCC5sUVpY23sDKXnvrYOUBbGITG0kQjQriPlgYhmF/3ryFjbIs82nVfEEBEiAB8k+Q+q1IkqSDNVq4lMy3scIkjuP0FSdbjNHMLys6OwyQVlnXEsOS2QP6OL8jkzlmd70jus86eBT8FIu8PqGXg6oFX6ARGthgX+V1ReFnDJAACZAfhFwHAJI7HF2lZGQaAAAAAElFTkSuQmCC) 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
|
||||
}
|
||||
}
|
|
@ -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";
|
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 13 KiB |
|
@ -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);
|
||||
}
|
||||
|
||||
?>
|
After Width: | Height: | Size: 2.4 KiB |
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
After Width: | Height: | Size: 496 B |
After Width: | Height: | Size: 243 B |
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|