simpler version without much js, just vanilla pure simple php (with some libs)
This commit is contained in:
parent
e70f536b1a
commit
e7f3446506
47 changed files with 1915 additions and 363 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
.idea
|
.idea
|
||||||
*.patch
|
*.patch
|
||||||
|
node_modules
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"php-imap/php-imap": "~2.0"
|
"php-imap/php-imap": "~2.0",
|
||||||
|
"gnugat/PronounceableWord": "*"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"vendor-dir": "src/backend-libs"
|
"vendor-dir": "src/backend-libs"
|
||||||
|
|
46
composer.lock
generated
46
composer.lock
generated
|
@ -4,9 +4,51 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "18ba77805fd530e1972050e6de7cd151",
|
"hash": "781cc38d2f745ec4bfba29e440111b80",
|
||||||
"content-hash": "357059f60b3f57be6e5f15b1df393a72",
|
"content-hash": "70878ea12bce14861844baa8032688de",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "gnugat/PronounceableWord",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git@github.com:gnugat/PronounceableWord.git",
|
||||||
|
"reference": "60a19dc7148e92de35ea536b9f873b86365d48f0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/gnugat/PronounceableWord/zipball/60a19dc7148e92de35ea536b9f873b86365d48f0",
|
||||||
|
"reference": "60a19dc7148e92de35ea536b9f873b86365d48f0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"PronounceableWord_": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Loïc Chardonnet"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A light, customizable and simple library generating random and pronounceable words without using dictionaries or Markov chains.",
|
||||||
|
"homepage": "https://github.com/gnugat/PronounceableWord",
|
||||||
|
"keywords": [
|
||||||
|
"generator",
|
||||||
|
"pronounceable",
|
||||||
|
"word"
|
||||||
|
],
|
||||||
|
"abandoned": true,
|
||||||
|
"time": "2012-01-08 19:36:58"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "php-imap/php-imap",
|
"name": "php-imap/php-imap",
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
// autoload.php @generated by Composer
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
return ComposerAutoloaderInit125dddd280a32cf75b181166154246ec::getLoader();
|
return ComposerAutoloaderInit125dddd280a32cf75b181166154246ec::getLoader();
|
||||||
|
|
|
@ -6,5 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||||
$baseDir = dirname(dirname($vendorDir));
|
$baseDir = dirname(dirname($vendorDir));
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'PronounceableWord_' => array($vendorDir . '/gnugat/PronounceableWord/src'),
|
||||||
'PhpImap' => array($vendorDir . '/php-imap/php-imap/src'),
|
'PhpImap' => array($vendorDir . '/php-imap/php-imap/src'),
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,6 +9,10 @@ class ComposerStaticInit125dddd280a32cf75b181166154246ec
|
||||||
public static $prefixesPsr0 = array (
|
public static $prefixesPsr0 = array (
|
||||||
'P' =>
|
'P' =>
|
||||||
array (
|
array (
|
||||||
|
'PronounceableWord_' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/gnugat/PronounceableWord/src',
|
||||||
|
),
|
||||||
'PhpImap' =>
|
'PhpImap' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/php-imap/php-imap/src',
|
0 => __DIR__ . '/..' . '/php-imap/php-imap/src',
|
||||||
|
|
|
@ -43,5 +43,49 @@
|
||||||
"mail",
|
"mail",
|
||||||
"php"
|
"php"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gnugat/PronounceableWord",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"version_normalized": "2.0.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git@github.com:gnugat/PronounceableWord.git",
|
||||||
|
"reference": "60a19dc7148e92de35ea536b9f873b86365d48f0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/gnugat/PronounceableWord/zipball/60a19dc7148e92de35ea536b9f873b86365d48f0",
|
||||||
|
"reference": "60a19dc7148e92de35ea536b9f873b86365d48f0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.2"
|
||||||
|
},
|
||||||
|
"time": "2012-01-08 19:36:58",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"PronounceableWord_": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Loïc Chardonnet"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A light, customizable and simple library generating random and pronounceable words without using dictionaries or Markov chains.",
|
||||||
|
"homepage": "https://github.com/gnugat/PronounceableWord",
|
||||||
|
"keywords": [
|
||||||
|
"generator",
|
||||||
|
"pronounceable",
|
||||||
|
"word"
|
||||||
|
],
|
||||||
|
"abandoned": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
1
src/backend-libs/gnugat/PronounceableWord/.gitignore
vendored
Normal file
1
src/backend-libs/gnugat/PronounceableWord/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/nbproject
|
35
src/backend-libs/gnugat/PronounceableWord/CHANGELOG.rst
Normal file
35
src/backend-libs/gnugat/PronounceableWord/CHANGELOG.rst
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
Change log
|
||||||
|
==========
|
||||||
|
|
||||||
|
This file will provide the main changes between each new versions.
|
||||||
|
|
||||||
|
To get the diff for a specific change, go to https://github.com/gnugat/PronounceableWord/commit/XXX
|
||||||
|
where XXX is the change hash.
|
||||||
|
|
||||||
|
To get the diff between two versions, go to https://github.com/gnugat/PronounceableWord/compare/X.Y.Z...A.B.C
|
||||||
|
where X.Y.Z and A.B.C are the tag names.
|
||||||
|
|
||||||
|
2.0.0 (2012-01-08)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* b9b3583: compatibility woth composer;
|
||||||
|
* 01a495a: using lower probability for LinkedLetters configuration;
|
||||||
|
* 8b27028: using a dependency injection container;
|
||||||
|
* 24bd26c: using dependency injection pattern;
|
||||||
|
* fe00216: complying to PSR-0 standard;
|
||||||
|
* c6c7ea1: importing documentation from wiki.
|
||||||
|
|
||||||
|
1.0.2 (2012-01-03)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* 1e34020: updating the version number.
|
||||||
|
|
||||||
|
1.0.1 (2012-01-03)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* 3af0bff: copyright extended to 2012.
|
||||||
|
|
||||||
|
1.0.0 (2011-12-17)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* a86dcea: Initial stable release.
|
27
src/backend-libs/gnugat/PronounceableWord/LICENSE.rst
Normal file
27
src/backend-libs/gnugat/PronounceableWord/LICENSE.rst
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
LICENSE
|
||||||
|
=======
|
||||||
|
|
||||||
|
License for the PronounceableWord PHP library
|
||||||
|
|
||||||
|
The MIT license
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Copyright (c) 2011-2012 Loic Chardonnet
|
||||||
|
|
||||||
|
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.
|
107
src/backend-libs/gnugat/PronounceableWord/README.rst
Normal file
107
src/backend-libs/gnugat/PronounceableWord/README.rst
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
PronounceableWord PHP library
|
||||||
|
=============================
|
||||||
|
|
||||||
|
A light, customizable and simple PHP (>= 5.2) library, used to generate
|
||||||
|
randomly pronounceable words, names and passwords without using database of
|
||||||
|
existing words or big samples of text like with Markov chains.
|
||||||
|
|
||||||
|
**Warning**
|
||||||
|
|
||||||
|
Offensive or insulting words might be generated because of the random nature
|
||||||
|
of the generator (see how to manage them in
|
||||||
|
``./doc/manageOffensiveAndInsultingWords.rst``).
|
||||||
|
|
||||||
|
Installation and usage
|
||||||
|
======================
|
||||||
|
|
||||||
|
First, get the last stable version, and put it in an accessible directory.
|
||||||
|
|
||||||
|
You can use composer to do so (http://packagist.org/), by adding in the
|
||||||
|
``require`` of your file ``./composer.json`` the following entry:
|
||||||
|
``"gnugat/PronounceableWord": "*"``.
|
||||||
|
|
||||||
|
You should have a fully operationnal pronounceable word generator::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 5);
|
||||||
|
define('MAXIMUM_LENGTH', 11);
|
||||||
|
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$word = $generator->generateWordOfGivenLength($length);
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
To customize the algorithm, the letters used, the linked letters or the types,
|
||||||
|
just copy and modify as you wish the files in the
|
||||||
|
``./src/PronounceableWord/Configuration`` directory and then pass your
|
||||||
|
configuration classes to the container (see how to configure in
|
||||||
|
``./doc/configuration.rst``).
|
||||||
|
|
||||||
|
Tests
|
||||||
|
-----
|
||||||
|
|
||||||
|
Tests are done using PHPUnit (https://github.com/sebastianbergmann/phpunit/)
|
||||||
|
(>=3.5) in the ``./test`` directory (see how to test in ``./doc/tests.rst``).
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Here is a sample of examples that can be generated (use the
|
||||||
|
``./bin/generateExamples.php`` script for more):
|
||||||
|
|
||||||
|
======= ====== ======= ======== =========
|
||||||
|
Length 5 6 7 8
|
||||||
|
======= ====== ======= ======== =========
|
||||||
|
1 vicas panori eropops absugrit
|
||||||
|
2 ramsa verifu simbous nimpiowi
|
||||||
|
3 kiclu impriar rubleru entumecu
|
||||||
|
4 posup bivary kitocra vemolior
|
||||||
|
5 utler rugisi kanomev pactabie
|
||||||
|
======= ====== ======= ======== =========
|
||||||
|
|
||||||
|
Algorithm
|
||||||
|
=========
|
||||||
|
|
||||||
|
Basically, the library will generate a word following these rules:
|
||||||
|
|
||||||
|
1. Choose randomly a letter;
|
||||||
|
2. choose randomly a linked letter of different type;
|
||||||
|
3. choose randomly a linked letter, of different type if the last letter is
|
||||||
|
of consecutive types.
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
* "linked letter" is an arbitrary chosen letter that is expected to follow
|
||||||
|
well the previous letter;
|
||||||
|
* "types" would be voyels and consonants;
|
||||||
|
* "consecutive" would be a group of two letters from the same "type".
|
||||||
|
|
||||||
|
The step 3 is repeated as many times as necessary.
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
=============
|
||||||
|
|
||||||
|
You can find more documentation at the following links:
|
||||||
|
|
||||||
|
* Copyright and MIT license: ``./LICENSE.rst``;
|
||||||
|
* version and change log: ``./VERSION.rst`` and ``CHANGELOG.rst``;
|
||||||
|
* technical and usage documentation: ``./doc/``.
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
============
|
||||||
|
|
||||||
|
1. Fork it: https://github.com/gnugat/PronounceableWord/fork_select ;
|
||||||
|
2. create a branch (``git checkout -b my_branch``);
|
||||||
|
3. commit your changes (``git commit -am "Changes description message"``);
|
||||||
|
4. push to the branch (``git push origin my_branch``);
|
||||||
|
5. create an Issue (https://github.com/gnugat/PronounceableWord/issues) with a
|
||||||
|
link to your branch;
|
||||||
|
6. wait for it to be accepted/argued.
|
10
src/backend-libs/gnugat/PronounceableWord/VERSION.rst
Normal file
10
src/backend-libs/gnugat/PronounceableWord/VERSION.rst
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
VERSION
|
||||||
|
=======
|
||||||
|
|
||||||
|
The purpose of this file is to point out the version of the PronounceableWord
|
||||||
|
library.
|
||||||
|
|
||||||
|
Current version
|
||||||
|
---------------
|
||||||
|
|
||||||
|
2.0.0
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 4);
|
||||||
|
define('MAXIMUM_LENGTH', 9);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
|
||||||
|
$maximumGenerationNumber = 20;
|
||||||
|
for ($generationNumber = 0; $generationNumber < $maximumGenerationNumber; $generationNumber++) {
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
echo $generator->generateWordOfGivenLength($length) . "\n";
|
||||||
|
}
|
21
src/backend-libs/gnugat/PronounceableWord/composer.json
Normal file
21
src/backend-libs/gnugat/PronounceableWord/composer.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "gnugat/PronounceableWord",
|
||||||
|
"type": "library",
|
||||||
|
"description": "A light, customizable and simple library generating random and pronounceable words without using dictionaries or Markov chains.",
|
||||||
|
"keywords": ["generator", "pronounceable", "word"],
|
||||||
|
"homepage": "https://github.com/gnugat/PronounceableWord",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Loic Chardonnet"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.2"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"PronounceableWord_": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
210
src/backend-libs/gnugat/PronounceableWord/doc/configuration.rst
Normal file
210
src/backend-libs/gnugat/PronounceableWord/doc/configuration.rst
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
To generate pronounceable words, **PronouceableWord** uses three types of
|
||||||
|
configuration:
|
||||||
|
|
||||||
|
================ ================================ ================================================
|
||||||
|
Configuration What it defines What it allows
|
||||||
|
================ ================================ ================================================
|
||||||
|
Linked letters The link between letters To know which letters can follow a letter
|
||||||
|
Letter types The types of the letters To alternate between consonants, vowels, etc...
|
||||||
|
Generator The number of consecutive types To know when to alternate the types
|
||||||
|
================ ================================ ================================================
|
||||||
|
|
||||||
|
PronouceableWord_Configuration_LinkedLetters
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
This class contains only one attribute (``lettersWithLinkedLetters``), which
|
||||||
|
is an associative array:
|
||||||
|
|
||||||
|
Key
|
||||||
|
A string of only one character representing the letter.
|
||||||
|
|
||||||
|
Value
|
||||||
|
A string representing the letters supposed to follow well the **key**.
|
||||||
|
|
||||||
|
For example, having ``'b' => 'a'`` will allow to compose ``'ba'``.
|
||||||
|
|
||||||
|
PronouceableWord_Configuration_LetterTypes
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
This class contains only one attribute (``letterTypesWithLetters``), which is
|
||||||
|
an associative array:
|
||||||
|
|
||||||
|
Key
|
||||||
|
The name of the type.
|
||||||
|
|
||||||
|
Value
|
||||||
|
A string containing the letters of this type.
|
||||||
|
|
||||||
|
For example, defining the vowels would be: ``'vowels' => 'aeiouy'``.
|
||||||
|
|
||||||
|
PronounceableWord_Configuration_Generator
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
This class contains two attributes which must be integers superior to 1.:
|
||||||
|
|
||||||
|
===================================== ==============================================================================
|
||||||
|
Attribute Example value and effect
|
||||||
|
===================================== ==============================================================================
|
||||||
|
maximumConsecutiveTypesAtTheBegining 1: if the first letter is a vowel, the second will be a consonant
|
||||||
|
maximumConsecutiveTypesInTheWord 2: if the second and third letters are vowels, the fourth will be a consonant
|
||||||
|
===================================== ==============================================================================
|
||||||
|
|
||||||
|
Default configuration
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The default configuration provides a set of linked letters based on the study
|
||||||
|
of Data Compression (http://www.data-compression.com/english.shtml#second),
|
||||||
|
using there statistical study of English text.
|
||||||
|
|
||||||
|
Some changes have been applied:
|
||||||
|
|
||||||
|
* only letters with a probability superior to 0.01 have been selected;
|
||||||
|
* the letters 'j' and 'q' have been removed.
|
||||||
|
|
||||||
|
How to customize the configuration
|
||||||
|
==================================
|
||||||
|
|
||||||
|
To customize the configuration, you need to:
|
||||||
|
|
||||||
|
1. copy the configuration classes in
|
||||||
|
``./vendor/PronounceableWord/src/PronounceableWord/Configuration`` to your
|
||||||
|
project configuration (e.g. ``./Configuration``);
|
||||||
|
2. change the name of your configuration classes to avoid confusion, (e.g.
|
||||||
|
replacing the prefix ``PronounceableWord`` by ``My``);
|
||||||
|
3. change the content as you wish;
|
||||||
|
4. set the configuration attributes in the dependency injection container
|
||||||
|
with your own classes.
|
||||||
|
|
||||||
|
How to test the configuration
|
||||||
|
=============================
|
||||||
|
|
||||||
|
To make sure your customized configuration is coherent and won't make
|
||||||
|
**PronounceableWord** crash, you can test it as follow:
|
||||||
|
|
||||||
|
1. create a unit test extending the configuration test (from
|
||||||
|
``./vendor/PronounceableWord/test/PronounceableWord/Tests/Configuration``);
|
||||||
|
2. override the ``setUp`` method by initializing the ``configuration``
|
||||||
|
attribute with your own configuration class.
|
||||||
|
|
||||||
|
To learn more about how to test, see ``./doc/tests.srt``.
|
||||||
|
|
||||||
|
Full Example
|
||||||
|
============
|
||||||
|
|
||||||
|
Here is a complete example, to show how it works.
|
||||||
|
|
||||||
|
Customizing
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The configuration::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File copied: "./vendor/PronounceableWord/src/PronounceableWord/Configuration/LinkedLetters.php"
|
||||||
|
// into: "./Configuration/LinkedLetters.php"
|
||||||
|
|
||||||
|
class My_Configuration_LinkedLetters {
|
||||||
|
public $lettersWithLinkedLetters = array(
|
||||||
|
'a' => 'bc',
|
||||||
|
'b' => 'ac',
|
||||||
|
'c' => 'a0',
|
||||||
|
'0' => 'abc',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File copied: "./vendor/PronounceableWord/src/PronounceableWord/Configuration/LetterTypes.php"
|
||||||
|
// into: "./Configuration/LetterTypes.php"
|
||||||
|
|
||||||
|
class My_Configuration_LetterTypes {
|
||||||
|
public $letterTypesWithLetters = array(
|
||||||
|
'vowels' => 'a',
|
||||||
|
'consonants' => 'bc',
|
||||||
|
'numbers' => '0',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File copied: "./vendor/PronounceableWord/src/PronounceableWord/Configuration/Generator.php"
|
||||||
|
// into: "./Configuration/Generator.php"
|
||||||
|
|
||||||
|
class My_Configuration_Generator {
|
||||||
|
public $maximumConsecutiveTypesAtTheBegining = 1;
|
||||||
|
public $maximumConsecutiveTypesInTheWord = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
This configuration is fine:
|
||||||
|
|
||||||
|
* each letters have at least one linked letters of a different type;
|
||||||
|
* there are at least two different types;
|
||||||
|
* every letters are present in the letter types;
|
||||||
|
* the number of consecutive types are strictly positives.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
To use it, just set them into the container::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
require_once dirname(__FILE__) . '/Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/Configuration/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/Configuration/Generator.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 5);
|
||||||
|
define('MAXIMUM_LENGTH', 11);
|
||||||
|
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$container->configurations['LinkedLetters'] = new My_Configuration_LinkedLetters();
|
||||||
|
$container->configurations['LetterTypes'] = new My_Configuration_LetterTypes();
|
||||||
|
$container->configurations['Generator'] = new My_Configuration_Generator();
|
||||||
|
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$word = $generator->generateWordOfGivenLength($length);
|
||||||
|
|
||||||
|
Testing
|
||||||
|
-------
|
||||||
|
|
||||||
|
To test it, create the following unit tests::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File /test/Configuration/LinkedLettersTest.php
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../vendor/PronounceableWord/test/PronounceableWord/Tests/Configuration/LinkedLettersTest.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../Configuration/LinkedLetters.php';
|
||||||
|
|
||||||
|
class My_Tests_Configuration_LinkedLettersTest extends PronounceableWord_Tests_Configuration_LinkedLettersTest {
|
||||||
|
public function setUp() {
|
||||||
|
$this->configuration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File /test/Configuration/LetterTypesTest.php
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../vendor/PronounceableWord/test/PronounceableWord/Tests/Configuration/LetterTypesTest.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../Configuration/LetterTypes.php';
|
||||||
|
|
||||||
|
class My_Tests_Configuration_LetterTypesTest extends PronounceableWord_Tests_Configuration_LetterTypesTest {
|
||||||
|
public function setUp() {
|
||||||
|
$this->configuration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File /test/Configuration/GeneratorTest.php
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../vendor/PronounceableWord/test/PronounceableWord/Tests/Configuration/GeneratorTest.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../Configuration/Generator.php';
|
||||||
|
|
||||||
|
class My_Tests_Configuration_GeneratorTest extends PronounceableWord_Tests_Configuration_GeneratorTest {
|
||||||
|
public function setUp() {
|
||||||
|
$this->configuration = new PronounceableWord_Configuration_Generator();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
Offensive and insulting words management
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Because PronounceableWord uses an algorithm using randomness,
|
||||||
|
offensive or insulting words might be generated. The best way to manage them
|
||||||
|
is to ceate a function that will filter them afterward.
|
||||||
|
|
||||||
|
These offensive words might be surrounded by other letters that would be fine
|
||||||
|
otherwise, so you should replace it by a non-offensive one instead of just
|
||||||
|
removing it.
|
||||||
|
|
||||||
|
To avoid generating unpronounceable words with this filter, try to be
|
||||||
|
consistent with the configuration.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
Here is an example on how to manage them. With the default configuration, the
|
||||||
|
word "insult" can be generated. Let's replace it by "insalt": the letter "s"
|
||||||
|
has "a" as a linked letter, and the letter "a" has "l" has a linked letter::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/OffensiveAndInsultingWords.php".
|
||||||
|
|
||||||
|
class OffensiveAndInsultingWords {
|
||||||
|
protected $offensiveAndInsultingWords = array(
|
||||||
|
'insult' => 'insalt',
|
||||||
|
);
|
||||||
|
|
||||||
|
public function filter($word) {
|
||||||
|
foreach ($this->offensiveAndInsultingWords as $offensiveAndInsultingWord => $replacement) {
|
||||||
|
$word = str_replace($offensiveAndInsultingWord, $replacement, $word);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Now, after generating your words with ``PronounceableWord_Generator``, you can
|
||||||
|
use ``OffensiveAndInsultingWords`` to filter any words you might find offensive
|
||||||
|
or insulting::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/OffensiveAndInsultingWords.php';
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 5);
|
||||||
|
define('MAXIMUM_LENGTH', 11);
|
||||||
|
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$offensiveAndInsultingWordManager = new OffensiveAndInsultingWords();
|
||||||
|
|
||||||
|
$word = $generator->generateWordOfGivenLength($length);
|
||||||
|
$word = offensiveAndInsultingWordManager->filter($word);
|
|
@ -0,0 +1,175 @@
|
||||||
|
The password generator example
|
||||||
|
==============================
|
||||||
|
|
||||||
|
This page is intended to provide an example of usage and configuration, to
|
||||||
|
generate passwords with PronounceableWord.
|
||||||
|
|
||||||
|
First create your project. You should have something like::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
First, get the last stable version, and put it in an accessible directory::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/Generator.php';
|
||||||
|
|
||||||
|
For now, you should have a fully operationnal generator::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 5);
|
||||||
|
define('MAXIMUM_LENGTH', 11);
|
||||||
|
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$password = $generator->generateWordOfGivenLength($length);
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
Let's say that the standard configuration doesn't please you, because you think
|
||||||
|
that password should also contain integers.
|
||||||
|
|
||||||
|
Linked letters configuration
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The first thing is to create your own linked letters configuration, with
|
||||||
|
integers::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "./Configuration/LinkedLetters.php"
|
||||||
|
class My_Configuration_LinkedLetters {
|
||||||
|
public $lettersWithLinkedLetters = array(
|
||||||
|
'a' => 'bcdgiklmnprstvy0123456789',
|
||||||
|
'b' => 'aeilorstuy0123456789',
|
||||||
|
'c' => 'acehiklortu0123456789',
|
||||||
|
'd' => 'aeiorsu0123456789',
|
||||||
|
'e' => 'acdeilmnprstvxy0123456789',
|
||||||
|
'f' => 'aefilortu0123456789',
|
||||||
|
'g' => 'aeghilnorsu0123456789',
|
||||||
|
'h' => 'aeiortu0123456789',
|
||||||
|
'i' => 'acdefglmnorstv0123456789',
|
||||||
|
'k' => 'aeilnos0123456789',
|
||||||
|
'l' => 'adefilostuy0123456789',
|
||||||
|
'm' => 'abeimoprsuy0123456789',
|
||||||
|
'n' => 'acdegiosty0123456789',
|
||||||
|
'o' => 'cdfklmnoprstuvw0123456789',
|
||||||
|
'p' => 'aehiloprstu0123456789',
|
||||||
|
'r' => 'acdegilmnorstuy0123456789',
|
||||||
|
's' => 'acehilopstu0123456789',
|
||||||
|
't' => 'aehilorstuy0123456789',
|
||||||
|
'u' => 'abcdegilmnprst0123456789',
|
||||||
|
'v' => 'aeino0123456789',
|
||||||
|
'w' => 'aehinos0123456789',
|
||||||
|
'x' => 'acehiptu0123456789',
|
||||||
|
'y' => 'eiost0123456789',
|
||||||
|
'z' => 'aeiloyz0123456789',
|
||||||
|
'0' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'1' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'2' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'3' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'4' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'5' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'6' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'7' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'8' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
'9' => 'abcdefghiklmnoprstuvwxyz0123456789',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Letter type configuration
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Then create the letter types configuration with integers::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "./Configuration/LetterTypes.php"
|
||||||
|
class My_Configuration_LetterTypes {
|
||||||
|
public $letterTypesWithLetters = array(
|
||||||
|
'voyels' => 'aeiouy',
|
||||||
|
'consonants' => 'bcdfghklmnprstvwxz',
|
||||||
|
'integers' => '0123456789',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Adding your configuration
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Finally, simply add your configuration into the container::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
require_once dirname(__FILE__) . './Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . './Configuration/LetterTypes.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 5);
|
||||||
|
define('MAXIMUM_LENGTH', 11);
|
||||||
|
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$container->configurations['LinkedLetters'] = new My_Configuration_LinkedLetters();
|
||||||
|
$container->configurations['LetterTypes'] = new My_Configuration_LetterTypes();
|
||||||
|
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$password = $generator->generateWordOfGivenLength($length);
|
||||||
|
|
||||||
|
Conclusion
|
||||||
|
==========
|
||||||
|
|
||||||
|
You now have a pronounceable password generator. If you want to use upper and
|
||||||
|
lower case, you should use a function aferwards::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "./addUppercase.php"
|
||||||
|
define('CHOOSE_LOWER_CASE', 0);
|
||||||
|
define('CHOOSE_UPPER_CASE', 1);
|
||||||
|
|
||||||
|
function addUppercase($word) {
|
||||||
|
$maximumLetterIndex = strlen($word);
|
||||||
|
for ($letterIndex = 0; $letterIndex < $maximumLetterIndex, $letterIndex++) {
|
||||||
|
$choice = rand(CHOOSE_LOWER_CASE, CHOOSE_UPPER_CASE);
|
||||||
|
if (CHOOSE_UPPER_CASE === $choice) {
|
||||||
|
$word[$letterIndex] = strtoupper($word[$letterIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $word;
|
||||||
|
}
|
||||||
|
|
||||||
|
And::
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// File "/index.php".
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/vendor/PronounceableWord/src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
require_once dirname(__FILE__) . './Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . './Configuration/LetterTypes.php';
|
||||||
|
|
||||||
|
define('MINIMUM_LENGTH', 5);
|
||||||
|
define('MAXIMUM_LENGTH', 11);
|
||||||
|
|
||||||
|
$length = rand(MINIMUM_LENGTH, MAXIMUM_LENGTH);
|
||||||
|
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$container->configurations['LinkedLetters'] = new My_Configuration_LinkedLetters();
|
||||||
|
$container->configurations['LetterTypes'] = new My_Configuration_LetterTypes();
|
||||||
|
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$password = $generator->generateWordOfGivenLength($length);
|
||||||
|
|
||||||
|
$password = addUppercase($password);
|
31
src/backend-libs/gnugat/PronounceableWord/doc/roadmap.rst
Normal file
31
src/backend-libs/gnugat/PronounceableWord/doc/roadmap.rst
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
Roadmap
|
||||||
|
=======
|
||||||
|
|
||||||
|
This file will establish the fetaures plan for the next versions.
|
||||||
|
|
||||||
|
2.1.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
The following features must be implemented to reach the version 2.1.0:
|
||||||
|
|
||||||
|
* Choice of first letter based on the letters following 'SPACE' in the
|
||||||
|
Data Compression study: http://www.data-compression.com/english.shtml#second;
|
||||||
|
* choice of last letter based on the letters coming before 'SPACE' in the
|
||||||
|
Data Compression study: http://www.data-compression.com/english.shtml#second.
|
||||||
|
|
||||||
|
2.0.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
In order to reach the version 2.0.0, the following features must be
|
||||||
|
implemented:
|
||||||
|
|
||||||
|
* moving the documentation from the Github wiki to the git repository;
|
||||||
|
* conforming to the standard PSR-0:
|
||||||
|
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md;
|
||||||
|
* using the Dependency Injection design pattern to load configuration:
|
||||||
|
http://en.wikipedia.org/wiki/Dependency_injection;
|
||||||
|
* using Dependency Injection Container;
|
||||||
|
* using, as the linked letters default configuration, letters from the Data
|
||||||
|
Compression study superior to 0.01 instead of 0.001:
|
||||||
|
http://www.data-compression.com/english.shtml#second;
|
||||||
|
* being compatible with composer.
|
40
src/backend-libs/gnugat/PronounceableWord/doc/tests.rst
Normal file
40
src/backend-libs/gnugat/PronounceableWord/doc/tests.rst
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
Tests
|
||||||
|
=====
|
||||||
|
|
||||||
|
In order to keep PronounceableWordGenerator stable and to maintain a high
|
||||||
|
quality, tests have been written using PHPUnit >= 3.5
|
||||||
|
(https://github.com/sebastianbergmann/phpunit/).
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
Before doing any test, you must do some installations.
|
||||||
|
|
||||||
|
Installing PEAR
|
||||||
|
---------------
|
||||||
|
|
||||||
|
PEAR (http://pear.php.net/) is necessary to use PHPUnit. To install it, follow
|
||||||
|
these instructions: http://pear.php.net/manual/en/installation.getting.php
|
||||||
|
|
||||||
|
If you are on Windows, and using WAMP or EasyPHP (or maybe others web
|
||||||
|
development plateforms), you might encounter the following error::
|
||||||
|
|
||||||
|
phar "C:\wamp\bin\php\php5.3.0\PEAR\go-pear.phar" does not have a signature PHP Warning: require_once(phar://go-pear.par/index.php): failed to open stream: phar error: invalid url or non-existent phar "phar://go-pear.phar/index.php" in C:\wamp\bin\php\php5.3.0\PEAR\go-pear.phar on line 1236
|
||||||
|
|
||||||
|
Warning: require_once(phar://go-pear.par/index.php): failed to open stream: phar error: invalid url or non-existent phar "phar://go-pear.phar/index.php" in C:\wamp\bin\php\php5.3.0\PEAR\go-pear.phar on line 1236 Press any key to continue...
|
||||||
|
|
||||||
|
This is because the PHP setting "phar.require_hash" is set to "On" by default.
|
||||||
|
If you set it to "Off" in your "php.ini", you should be able to continue.
|
||||||
|
|
||||||
|
Installing PHPUnit
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Once PEAR is installed, you can use it to install PHPUnit by following these
|
||||||
|
instructions: http://www.phpunit.de/manual/3.0/en/installation.html
|
||||||
|
|
||||||
|
Running the tests
|
||||||
|
=================
|
||||||
|
|
||||||
|
Tests can be run by CLI, using the following command::
|
||||||
|
|
||||||
|
phpunit ./test
|
|
@ -0,0 +1,54 @@
|
||||||
|
Versionning
|
||||||
|
===========
|
||||||
|
|
||||||
|
This file will document the versionning process of the PHP library
|
||||||
|
PronounceableWord.
|
||||||
|
|
||||||
|
Version number
|
||||||
|
==============
|
||||||
|
|
||||||
|
The version number will follow the X.Y.Z format. The following table describes
|
||||||
|
the meaning of incrementation for each number:
|
||||||
|
|
||||||
|
======== =============================================================================================
|
||||||
|
Version Description
|
||||||
|
======== =============================================================================================
|
||||||
|
#.0.0 Modification impacting on the public usage
|
||||||
|
0.#.0 Modification not impacting on the public usage
|
||||||
|
0.0.# Small modification not impacting on the public usage, like bug fixes and adding of new tests
|
||||||
|
======== =============================================================================================
|
||||||
|
|
||||||
|
Branching model
|
||||||
|
===============
|
||||||
|
|
||||||
|
The PronounceableWord project uses Git to its full potential, following
|
||||||
|
the advice of this article:
|
||||||
|
http://nvie.com/posts/a-successful-git-branching-model/ .
|
||||||
|
|
||||||
|
================== =============== ================================= ====================================
|
||||||
|
Repository/Branch Pull from Merge to Description
|
||||||
|
================== =============== ================================= ====================================
|
||||||
|
origin/master Stable branch, actual release.
|
||||||
|
origin/develop origin/master origin/master Stable branch, for next release.
|
||||||
|
x/hotfix-* origin/master origin/master and origin/develop Bug fixes branch for origin/master.
|
||||||
|
x/x origin/develop origin/develop Feature branch.
|
||||||
|
================== =============== ================================= ====================================
|
||||||
|
|
||||||
|
Tags
|
||||||
|
----
|
||||||
|
|
||||||
|
Tags are created from the origin/master branch, incrementing the version number.
|
||||||
|
|
||||||
|
x/hotfix-* branches
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The repository is named x because it can be from another repository (through
|
||||||
|
forks), and the branch is called hotfix-* because it is suffixed by "hotfix-"
|
||||||
|
and named after the feature it will fix.
|
||||||
|
|
||||||
|
x/x branches
|
||||||
|
------------
|
||||||
|
|
||||||
|
The repository is named x because it can be from another repository (through
|
||||||
|
forks), and the branch is called x because it is named after the feature it
|
||||||
|
will implement.
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
class PronounceableWord_Configuration_Generator {
|
||||||
|
public $maximumConsecutiveTypesAtTheBegining = 1;
|
||||||
|
public $maximumConsecutiveTypesInTheWord = 2;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
class PronounceableWord_Configuration_LetterTypes {
|
||||||
|
public $letterTypesWithLetters = array(
|
||||||
|
'voyels' => 'aeiouy',
|
||||||
|
'consonants' => 'bcdfghklmnprstvwxz',
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
class PronounceableWord_Configuration_LinkedLetters {
|
||||||
|
public $lettersWithLinkedLetters = array(
|
||||||
|
'a' => 'bcdgiklmnprstvy',
|
||||||
|
'b' => 'aeilorstuy',
|
||||||
|
'c' => 'acehiklortu',
|
||||||
|
'd' => 'aeiorsu',
|
||||||
|
'e' => 'acdeilmnprstvxy',
|
||||||
|
'f' => 'aefilortu',
|
||||||
|
'g' => 'aeghilnorsu',
|
||||||
|
'h' => 'aeiortu',
|
||||||
|
'i' => 'acdefglmnorstv',
|
||||||
|
'k' => 'aeilnos',
|
||||||
|
'l' => 'adefilostuy',
|
||||||
|
'm' => 'abeimoprsuy',
|
||||||
|
'n' => 'acdegiosty',
|
||||||
|
'o' => 'cdfklmnoprstuvw',
|
||||||
|
'p' => 'aehiloprstu',
|
||||||
|
'r' => 'acdegilmnorstuy',
|
||||||
|
's' => 'acehilopstu',
|
||||||
|
't' => 'aehilorstuy',
|
||||||
|
'u' => 'abcdegilmnprst',
|
||||||
|
'v' => 'aeino',
|
||||||
|
'w' => 'aehinos',
|
||||||
|
'x' => 'acehiptu',
|
||||||
|
'y' => 'eiost',
|
||||||
|
'z' => 'aeiloyz',
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/Configuration/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/Configuration/Generator.php';
|
||||||
|
require_once dirname(__FILE__) . '/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/LastLettersConsecutiveTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/Generator.php';
|
||||||
|
|
||||||
|
class PronounceableWord_DependencyInjectionContainer {
|
||||||
|
public $configurations = array();
|
||||||
|
public $classNames = array();
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->configurations['Generator'] = new PronounceableWord_Configuration_Generator();
|
||||||
|
$this->configurations['LinkedLetters'] = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
$this->configurations['LetterTypes'] = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
|
||||||
|
$this->classNames['LinkedLetters'] = 'PronounceableWord_LinkedLetters';
|
||||||
|
$this->classNames['LetterTypes'] = 'PronounceableWord_LetterTypes';
|
||||||
|
$this->classNames['LastLettersConsecutiveTypes'] = 'PronounceableWord_LastLettersConsecutiveTypes';
|
||||||
|
$this->classNames['Generator'] = 'PronounceableWord_Generator';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGenerator() {
|
||||||
|
$generatorClass = $this->classNames['Generator'];
|
||||||
|
$generatorInstance = new $generatorClass(
|
||||||
|
$this->getLinkedLetters(),
|
||||||
|
$this->getLetterTypes(),
|
||||||
|
$this->getLastLettersConsecutiveTypes(),
|
||||||
|
$this->configurations['Generator']
|
||||||
|
);
|
||||||
|
|
||||||
|
return $generatorInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLinkedLetters() {
|
||||||
|
$linkedLettersClass = $this->classNames['LinkedLetters'];
|
||||||
|
$linkedLettersInstance = new $linkedLettersClass($this->configurations['LinkedLetters']);
|
||||||
|
|
||||||
|
return $linkedLettersInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLetterTypes() {
|
||||||
|
$lettersTypesClass = $this->classNames['LetterTypes'];
|
||||||
|
$lettersTypesInstance = new $lettersTypesClass($this->configurations['LetterTypes']);
|
||||||
|
|
||||||
|
return $lettersTypesInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLastLettersConsecutiveTypes() {
|
||||||
|
$lastLettersConsecutiveTypesClass = $this->classNames['LastLettersConsecutiveTypes'];
|
||||||
|
$lastLettersConsecutiveTypesInstance = new $lastLettersConsecutiveTypesClass($this->getLetterTypes());
|
||||||
|
|
||||||
|
return $lastLettersConsecutiveTypesInstance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PronounceableWord_Generator {
|
||||||
|
protected $word;
|
||||||
|
protected $length;
|
||||||
|
|
||||||
|
protected $linkedLetters;
|
||||||
|
protected $letterTypes;
|
||||||
|
protected $lastLettersConsecutiveTypes;
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
public function __construct($linkedLetter, $letterTypes, $lastLettersConsecutiveTypes, $configuration) {
|
||||||
|
$this->linkedLetters = $linkedLetter;
|
||||||
|
$this->letterTypes = $letterTypes;
|
||||||
|
$this->lastLettersConsecutiveTypes = $lastLettersConsecutiveTypes;
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateWordOfGivenLength($givenLength) {
|
||||||
|
$this->word = '';
|
||||||
|
$this->length = 0;
|
||||||
|
for ($letterNumber = 0; $letterNumber < $givenLength; $letterNumber++) {
|
||||||
|
$this->word .= $this->pickNextLetter();
|
||||||
|
$this->length = strlen($this->word);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->word;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pickNextLetter() {
|
||||||
|
$pickedLetter = '';
|
||||||
|
|
||||||
|
if (0 === $this->length) {
|
||||||
|
$pickedLetter = $this->pickFirstLetter();
|
||||||
|
} elseif ($this->length <= $this->configuration->maximumConsecutiveTypesAtTheBegining) {
|
||||||
|
$pickedLetter = $this->pickLinkedLetterOfDifferentType($this->word[0]);
|
||||||
|
} else {
|
||||||
|
$pickedLetter = $this->pickLinkedLetterOfDifferentTypeIfLastLettersAreOfConsecutiveTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pickedLetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pickFirstLetter() {
|
||||||
|
return $this->linkedLetters->pickLetter();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pickLinkedLetterOfDifferentType($letter) {
|
||||||
|
$letterType = $this->letterTypes->getLetterType($letter);
|
||||||
|
$lettersToAvoid = $this->letterTypes->getLettersOfGivenType($letterType);
|
||||||
|
|
||||||
|
return $this->linkedLetters->pickLinkedLetterDifferentFromGivenLetters($letter, $lettersToAvoid);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pickLinkedLetterOfDifferentTypeIfLastLettersAreOfConsecutiveTypes() {
|
||||||
|
$lastLetter = $this->word[$this->length - 1];
|
||||||
|
$consecutiveTypes = $this->lastLettersConsecutiveTypes->countFromWord($this->word);
|
||||||
|
|
||||||
|
$pickedLetter = '';
|
||||||
|
if ($consecutiveTypes === $this->configuration->maximumConsecutiveTypesInTheWord) {
|
||||||
|
$pickedLetter = $this->pickLinkedLetterOfDifferentType($lastLetter);
|
||||||
|
} else {
|
||||||
|
$pickedLetter = $this->linkedLetters->pickLinkedLetter($lastLetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pickedLetter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PronounceableWord_LastLettersConsecutiveTypes {
|
||||||
|
protected $letterTypes;
|
||||||
|
|
||||||
|
public function __construct($letterTypes) {
|
||||||
|
$this->letterTypes = $letterTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countFromWord($word) {
|
||||||
|
$letterIndex = strlen($word) - 1;
|
||||||
|
$letter = $word[$letterIndex];
|
||||||
|
$type = $this->letterTypes->getLetterType($letter);
|
||||||
|
$consecutiveTypesCount = 1;
|
||||||
|
|
||||||
|
for ($letterIndex = $letterIndex - 1; $letterIndex >= 0; $letterIndex--) {
|
||||||
|
$letter = $word[$letterIndex];
|
||||||
|
if ($this->letterTypes->getLetterType($letter) !== $type) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$consecutiveTypesCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $consecutiveTypesCount;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PronounceableWord_LetterTypes {
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
public function __construct($configuration) {
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLetterType($letter) {
|
||||||
|
$type = '';
|
||||||
|
foreach ($this->configuration->letterTypesWithLetters as $letterType => $letters) {
|
||||||
|
if (false !== strpos($letters, $letter)) {
|
||||||
|
$type = $letterType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLettersOfGivenType($type) {
|
||||||
|
return $this->configuration->letterTypesWithLetters[$type];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PronounceableWord_LinkedLetters {
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
public function __construct($configuration) {
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
}
|
||||||
|
public function pickLetter() {
|
||||||
|
$pickedLetter = array_rand($this->configuration->lettersWithLinkedLetters);
|
||||||
|
|
||||||
|
return $pickedLetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pickLinkedLetter($letter) {
|
||||||
|
$linkedLetters = $this->configuration->lettersWithLinkedLetters[$letter];
|
||||||
|
|
||||||
|
return $this->pickLetterFromGivenLetters($linkedLetters);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pickLetterFromGivenLetters($letters) {
|
||||||
|
$minLetterIndex = 0;
|
||||||
|
$maxLetterIndex = strlen($letters) - 1;
|
||||||
|
$pickedLetterIndex = rand($minLetterIndex, $maxLetterIndex);
|
||||||
|
|
||||||
|
$pickedLetter = $letters[$pickedLetterIndex];
|
||||||
|
|
||||||
|
return $pickedLetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pickLinkedLetterDifferentFromGivenLetters($letter, $letters) {
|
||||||
|
$linkedLetters = $this->configuration->lettersWithLinkedLetters[$letter];
|
||||||
|
|
||||||
|
$letterChoices = $this->removeGivenLettersFromGivenLinkedLetters($letters, $linkedLetters);
|
||||||
|
|
||||||
|
return $this->pickLetterFromGivenLetters($letterChoices);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function removeGivenLettersFromGivenLinkedLetters($letters, $linkedLetters) {
|
||||||
|
$maximumLetterIndex = strlen($letters);
|
||||||
|
for ($letterIndex = 0; $letterIndex < $maximumLetterIndex; $letterIndex++) {
|
||||||
|
$linkedLetters = str_replace($letters[$letterIndex], '', $linkedLetters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $linkedLetters;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../../src/PronounceableWord/Configuration/Generator.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_Configuration_GeneratorTest extends PHPUnit_Framework_TestCase {
|
||||||
|
protected $minimumPositiveNumber = 1;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->configuration = new PronounceableWord_Configuration_Generator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsMaximumConsecutiveTypesAtTheBeginingPositive() {
|
||||||
|
$this->assertGreaterThanOrEqual($this->minimumPositiveNumber, $this->configuration->maximumConsecutiveTypesAtTheBegining);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsMaximumConsecutiveTypesInTheWordPositive() {
|
||||||
|
$this->assertGreaterThanOrEqual($this->minimumPositiveNumber, $this->configuration->maximumConsecutiveTypesInTheWord);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../../src/PronounceableWord/Configuration/LetterTypes.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_Configuration_LetterTypesTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function setUp() {
|
||||||
|
$this->configuration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
}
|
||||||
|
public function testAreLettersInOnlyOneType() {
|
||||||
|
foreach ($this->configuration->letterTypesWithLetters as $currentType => $lettersOfCurrentType) {
|
||||||
|
$maximumLetterIndex = strlen($lettersOfCurrentType);
|
||||||
|
$areLettersInOnlyOneType = true;
|
||||||
|
foreach ($this->configuration->letterTypesWithLetters as $checkedType => $lettersOfCheckedType) {
|
||||||
|
if ($currentType !== $checkedType) {
|
||||||
|
for ($letterIndex = 0; $letterIndex < $maximumLetterIndex; $letterIndex++) {
|
||||||
|
$isLetterInLetters = strpos($lettersOfCheckedType, $lettersOfCurrentType[$letterIndex]);
|
||||||
|
|
||||||
|
if (false !== $isLetterInLetters) {
|
||||||
|
$areLettersInOnlyOneType = false;
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($areLettersInOnlyOneType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../../src/PronounceableWord/Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../../src/PronounceableWord/Configuration/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../../src/PronounceableWord/LetterTypes.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_Configuration_LinkedLettersAndTypesTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function setUp() {
|
||||||
|
$this->letterTypesConfiguration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$this->linkedLettersConfiguration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAreAllLettersFromLinkedLettersInLettersFromLetterTypes() {
|
||||||
|
foreach ($this->linkedLettersConfiguration->lettersWithLinkedLetters as $letter => $linkedLettersToIgnore) {
|
||||||
|
$isLetterInTypes = false;
|
||||||
|
foreach ($this->letterTypesConfiguration->letterTypesWithLetters as $lettersOfType) {
|
||||||
|
$isLetterInLetters = strpos($lettersOfType, $letter);
|
||||||
|
|
||||||
|
if (false !== $isLetterInLetters) {
|
||||||
|
$isLetterInTypes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($isLetterInTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHaveLettersAtLeastOneLinkedLetterOfDifferentType() {
|
||||||
|
$letterTypes = new PronounceableWord_LetterTypes($this->letterTypesConfiguration);
|
||||||
|
$linkedLettersConfiguration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
|
||||||
|
foreach ($this->linkedLettersConfiguration->lettersWithLinkedLetters as $letter => $linkedLetters) {
|
||||||
|
$letterType = $letterTypes->getLetterType($letter);
|
||||||
|
|
||||||
|
$hasOneDifferentType = false;
|
||||||
|
$maximumLetterIndex = strlen($linkedLetters);
|
||||||
|
for ($letterIndex = 0; $letterIndex < $maximumLetterIndex; $letterIndex++) {
|
||||||
|
$linkedLetterType = $letterTypes->getLetterType($linkedLetters[$letterIndex]);
|
||||||
|
|
||||||
|
if ($letterType !== $linkedLetterType) {
|
||||||
|
$hasOneDifferentType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($hasOneDifferentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../../src/PronounceableWord/Configuration/LinkedLetters.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_Configuration_LinkedLettersTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function setUp() {
|
||||||
|
$this->configuration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAreAllLettersInAtLeastOneLinkedLetters() {
|
||||||
|
foreach ($this->configuration->lettersWithLinkedLetters as $letter => $linkedLettersToIgnore) {
|
||||||
|
$isInAtLeastOneLinkedLetters = false;
|
||||||
|
foreach ($this->configuration->lettersWithLinkedLetters as $letterToIgnore => $linkedLetters) {
|
||||||
|
$isLetterInLinkedLetters = strpos($linkedLetters, $letter);
|
||||||
|
|
||||||
|
if (false !== $isLetterInLinkedLetters) {
|
||||||
|
$isInAtLeastOneLinkedLetters = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($isInAtLeastOneLinkedLetters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAreAllLinkedLettersInLetters() {
|
||||||
|
foreach ($this->configuration->lettersWithLinkedLetters as $letterToIgnore => $linkedLetters) {
|
||||||
|
$isLinkedLetterInLetters = false;
|
||||||
|
foreach ($this->configuration->lettersWithLinkedLetters as $letter => $linkedLettersToIgnore) {
|
||||||
|
$isLetterInLinkedLetters = strpos($linkedLetters, $letter);
|
||||||
|
|
||||||
|
if (false !== $isLetterInLinkedLetters) {
|
||||||
|
$isInAtLeastOneLinkedLetters = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($isInAtLeastOneLinkedLetters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/DependencyInjectionContainer.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_DependencyInjectionContainerTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function testClassNames() {
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
|
||||||
|
foreach ($container->classNames as $classType => $className) {
|
||||||
|
$expectedClassName = 'PronounceableWord_' . $classType;
|
||||||
|
$this->assertSame($expectedClassName, $className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testClassNamesAndInstances() {
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
|
||||||
|
foreach ($container->classNames as $classType => $className) {
|
||||||
|
$getMethodName = 'get' . $classType;
|
||||||
|
$instance = $container->{$getMethodName}();
|
||||||
|
|
||||||
|
$this->assertInstanceOf($className, $instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConfigurations() {
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
|
||||||
|
foreach ($container->configurations as $className => $configurationInstance) {
|
||||||
|
$configurationClassName = 'PronounceableWord_Configuration_' . $className;
|
||||||
|
|
||||||
|
$this->assertInstanceOf($configurationClassName, $configurationInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Configuration/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Configuration/Generator.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LastLettersConsecutiveTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Generator.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_GeneratorTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function testGeneratedLength() {
|
||||||
|
$linkedLettersConfiguration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
$letterTypesConfiguration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$generatorConfiguration = new PronounceableWord_Configuration_Generator();
|
||||||
|
|
||||||
|
$linkedLetters = new PronounceableWord_LinkedLetters($linkedLettersConfiguration);
|
||||||
|
$letterTypes = new PronounceableWord_LetterTypes($letterTypesConfiguration);
|
||||||
|
$lastLettersConsecutiveTypes = new PronounceableWord_LastLettersConsecutiveTypes($letterTypes);
|
||||||
|
|
||||||
|
$maximumLength = 100;
|
||||||
|
for ($length = 1; $length <= $maximumLength; $length++) {
|
||||||
|
$generator = new PronounceableWord_Generator($linkedLetters, $letterTypes, $lastLettersConsecutiveTypes, $generatorConfiguration);
|
||||||
|
|
||||||
|
$generatedWord = $generator->generateWordOfGivenLength($length);
|
||||||
|
|
||||||
|
$this->assertEquals($length, strlen($generatedWord));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Configuration/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LastLettersConsecutiveTypes.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_LastLettersConsecutiveTypesTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function testCountFromWordOfOneType() {
|
||||||
|
$letterTypesConfiguration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$letterTypes = new PronounceableWord_LetterTypes($letterTypesConfiguration);
|
||||||
|
$lastLettersConsecutiveTypes = new PronounceableWord_LastLettersConsecutiveTypes($letterTypes);
|
||||||
|
|
||||||
|
foreach ($letterTypesConfiguration->letterTypesWithLetters as $letterType => $letters) {
|
||||||
|
$maximumLetterNumber = strlen($letters);
|
||||||
|
$word = '';
|
||||||
|
for ($letterNumber = 1; $letterNumber < $maximumLetterNumber; $letterNumber++) {
|
||||||
|
$letter = rand(0, strlen($letters) - 1);
|
||||||
|
$word .= $letters[$letter];
|
||||||
|
|
||||||
|
$this->assertSame($letterNumber, $lastLettersConsecutiveTypes->countFromWord($word));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCountFromWordOfMultipleTypes() {
|
||||||
|
$letterTypesConfiguration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$letterTypes = new PronounceableWord_LetterTypes($letterTypesConfiguration);
|
||||||
|
$lastLettersConsecutiveTypes = new PronounceableWord_LastLettersConsecutiveTypes($letterTypes);
|
||||||
|
|
||||||
|
foreach ($letterTypesConfiguration->letterTypesWithLetters as $letterType => $letters) {
|
||||||
|
$maximumLetterNumber = strlen($letters);
|
||||||
|
|
||||||
|
foreach ($letterTypesConfiguration->letterTypesWithLetters as $otherLetterType => $otherLetters) {
|
||||||
|
if ($otherLetterType != $letterType) {
|
||||||
|
$word = $otherLetters;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($letterNumber = 1; $letterNumber < $maximumLetterNumber; $letterNumber++) {
|
||||||
|
$letter = rand(0, strlen($letters) - 1);
|
||||||
|
$word .= $letters[$letter];
|
||||||
|
|
||||||
|
$this->assertSame($letterNumber, $lastLettersConsecutiveTypes->countFromWord($word));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Configuration/LetterTypes.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LetterTypes.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_LetterTypesTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function testGetLetterType() {
|
||||||
|
$configuration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$letterTypes = new PronounceableWord_LetterTypes($configuration);
|
||||||
|
|
||||||
|
foreach ($configuration->letterTypesWithLetters as $letterType => $letters) {
|
||||||
|
$maximumLetterIndex = strlen($letters);
|
||||||
|
for ($letterIndex = 0; $letterIndex < $maximumLetterIndex; $letterIndex++) {
|
||||||
|
$letter = $letters[$letterIndex];
|
||||||
|
|
||||||
|
$this->assertSame($letterType, $letterTypes->getLetterType($letter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLettersOfGivenType() {
|
||||||
|
$configuration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$letterTypes = new PronounceableWord_LetterTypes($configuration);
|
||||||
|
|
||||||
|
foreach ($configuration->letterTypesWithLetters as $letterType => $letters) {
|
||||||
|
$this->assertSame($letters, $letterTypes->getLettersOfGivenType($letterType));
|
||||||
|
$maximumLetterIndex = strlen($letters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsThereAtLeastTwoTypes() {
|
||||||
|
$configuration = new PronounceableWord_Configuration_LetterTypes();
|
||||||
|
$minimumLetterTypesNumber = 2;
|
||||||
|
|
||||||
|
$this->assertGreaterThanOrEqual($minimumLetterTypesNumber, $configuration->letterTypesWithLetters);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the PronounceableWord library.
|
||||||
|
*
|
||||||
|
* (c) Loic Chardonnet
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE.txt
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/Configuration/LinkedLetters.php';
|
||||||
|
require_once dirname(__FILE__) . '/../../../src/PronounceableWord/LinkedLetters.php';
|
||||||
|
|
||||||
|
class PronounceableWord_Tests_LinkedLettersTest extends PHPUnit_Framework_TestCase {
|
||||||
|
public function testPickLetter() {
|
||||||
|
$configuration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
$linkedLetters = new PronounceableWord_LinkedLetters($configuration);
|
||||||
|
|
||||||
|
$maximumTestNumber = 1000;
|
||||||
|
for ($currentTestNumber = 0; $currentTestNumber < $maximumTestNumber; $currentTestNumber++) {
|
||||||
|
$chosenLetter = $linkedLetters->pickLetter();
|
||||||
|
|
||||||
|
$this->assertArrayHasKey($chosenLetter, $configuration->lettersWithLinkedLetters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPickLinkedLetter() {
|
||||||
|
$configuration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
$linkedLetters = new PronounceableWord_LinkedLetters($configuration);
|
||||||
|
|
||||||
|
$maximumTestNumber = 1000;
|
||||||
|
foreach ($configuration->lettersWithLinkedLetters as $currentLetter => $currentLinkedLetters) {
|
||||||
|
for ($currentTestNumber = 0; $currentTestNumber < $maximumTestNumber; $currentTestNumber++) {
|
||||||
|
$chosenLinkedLetter = $linkedLetters->pickLinkedLetter($currentLetter);
|
||||||
|
|
||||||
|
$isChosenLetterInLinkedLetters = strpos($currentLinkedLetters, $chosenLinkedLetter);
|
||||||
|
|
||||||
|
$this->assertNotEquals(false, $isChosenLetterInLinkedLetters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPickLinkedLetterDifferentFromGivenLetters() {
|
||||||
|
$configuration = new PronounceableWord_Configuration_LinkedLetters();
|
||||||
|
$linkedLetters = new PronounceableWord_LinkedLetters($configuration);
|
||||||
|
|
||||||
|
$maximumTestNumber = 1000;
|
||||||
|
foreach ($configuration->lettersWithLinkedLetters as $currentLetter => $currentLinkedLetters) {
|
||||||
|
for ($currentTestNumber = 0; $currentTestNumber < $maximumTestNumber; $currentTestNumber++) {
|
||||||
|
$chosenLinkedLetter = $linkedLetters->pickLinkedLetterDifferentFromGivenLetters($currentLetter, $currentLetter);
|
||||||
|
|
||||||
|
$isChosenLetterInLinkedLetters = strpos($currentLinkedLetters, $chosenLinkedLetter);
|
||||||
|
|
||||||
|
$isChosenLetterDifferentThanCurrentLetter = false;
|
||||||
|
if ($chosenLinkedLetter !== $currentLetter) {
|
||||||
|
$isChosenLetterDifferentThanCurrentLetter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$isChosenLetterValid = false;
|
||||||
|
if (false !== $isChosenLetterInLinkedLetters && true === $isChosenLetterDifferentThanCurrentLetter) {
|
||||||
|
$isChosenLetterValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($isChosenLetterValid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,10 +22,10 @@ function error($status, $text) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* print all mails for the given $user.
|
* print all mails for the given $user.
|
||||||
* @param $username string username
|
|
||||||
* @param $address string email address
|
* @param $address string email address
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
function print_emails($username, $address) {
|
function get_emails($address) {
|
||||||
global $mailbox;
|
global $mailbox;
|
||||||
|
|
||||||
// Search for mails with the recipient $address in TO or CC.
|
// Search for mails with the recipient $address in TO or CC.
|
||||||
|
@ -34,8 +34,7 @@ function print_emails($username, $address) {
|
||||||
$mail_ids = array_merge($mailsIdsTo, $mailsIdsCc);
|
$mail_ids = array_merge($mailsIdsTo, $mailsIdsCc);
|
||||||
|
|
||||||
$emails = _load_emails($mail_ids, $address);
|
$emails = _load_emails($mail_ids, $address);
|
||||||
header('Content-type: application/json');
|
return $emails;
|
||||||
print(json_encode(array("mails" => $emails, 'username' => $username, 'address' => $address)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,6 +125,25 @@ function _clean_username($username) {
|
||||||
return preg_replace('/[^A-Za-z0-9_.+-]/', "", $username); // remove special characters
|
return preg_replace('/[^A-Za-z0-9_.+-]/', "", $username); // remove special characters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _clean_domain($username) {
|
||||||
|
$username = strtolower($username);
|
||||||
|
$username = preg_replace('/^.*@/', "", $username); // remove part before @
|
||||||
|
return preg_replace('/[^A-Za-z0-9_.+-]/', "", $username); // remove special characters
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirect_to_random($domains) {
|
||||||
|
$wordLength = rand(3, 8);
|
||||||
|
$container = new PronounceableWord_DependencyInjectionContainer();
|
||||||
|
$generator = $container->getGenerator();
|
||||||
|
$word = $generator->generateWordOfGivenLength($wordLength);
|
||||||
|
$nr = rand(51, 91);
|
||||||
|
$name = $word . $nr;
|
||||||
|
|
||||||
|
$domain = $domains[array_rand($domains)];
|
||||||
|
|
||||||
|
header("location: ?address=$name@$domain");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deletes messages older than X days.
|
* deletes messages older than X days.
|
||||||
*/
|
*/
|
||||||
|
@ -139,30 +157,11 @@ function delete_old_messages() {
|
||||||
$mailbox->expungeDeletedMails();
|
$mailbox->expungeDeletedMails();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never cache requests:
|
//
|
||||||
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
//// Never cache requests:
|
||||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
//header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
||||||
header("Pragma: no-cache");
|
//header("Cache-Control: post-check=0, pre-check=0", false);
|
||||||
|
//header("Pragma: no-cache");
|
||||||
if (isset($_GET['username'])) {
|
|
||||||
// perform common validation:
|
|
||||||
$username = _clean_username($_GET['username']);
|
|
||||||
if (strlen($username) === 0) {
|
|
||||||
error(400, 'invalid username');
|
|
||||||
}
|
|
||||||
$address = $username . "@" . $config['mailHostname'];
|
|
||||||
|
|
||||||
// simple router:
|
|
||||||
if (isset($_GET['download_email_id'])) {
|
|
||||||
download_email($_GET['download_email_id'], $address);
|
|
||||||
} else if (isset($_GET['delete_email_id'])) {
|
|
||||||
delete_email($_GET['delete_email_id'], $address);
|
|
||||||
} else {
|
|
||||||
print_emails($username, $address);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error(400, 'invalid action');
|
|
||||||
}
|
|
||||||
|
|
||||||
// run on every request
|
// run on every request
|
||||||
delete_old_messages();
|
delete_old_messages();
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
[ec-stickyfill] {
|
|
||||||
position: -webkit-sticky;
|
|
||||||
position: sticky;
|
|
||||||
top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ec-stickyfill]:before,
|
|
||||||
[ec-stickyfill]:after {
|
|
||||||
content: '';
|
|
||||||
display: table;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
/**
|
|
||||||
* An Angular directive for stickyfill (position sticky polyfill)
|
|
||||||
*
|
|
||||||
* @version v0.1.0 - 2016-08-31
|
|
||||||
* @author Corey Wilson <corey@eastcodes.com>
|
|
||||||
* @license Unlicense, http://unlicense.org/
|
|
||||||
*/
|
|
||||||
!function(e,i){"use strict";if("function"==typeof define&&define.amd)define(["angular","stickyfill"],i);else{if("undefined"==typeof module||"object"!=typeof module.exports)return i(e.angular,e.Stickyfill);module.exports=i(require("angular"),require("stickyfill"))}}(window,function(e,i){"use strict";function t(){function e(e,t,n){if("object"!=typeof i)throw new Error("stickyfill.js not loaded");i.add(t[0]),e.$on("$destroy",function(){i.remove(t[0])})}var t={link:e,restrict:"A"};return t}if("function"==typeof i)var i=i();var n="ec.stickyfill";return e.module(n,[]).directive("ecStickyfill",t),n});
|
|
|
@ -1,137 +0,0 @@
|
||||||
// config:
|
|
||||||
var reload_interval_ms = 10000;
|
|
||||||
var backend_url = './backend.php';
|
|
||||||
|
|
||||||
function generateRandomUsername() {
|
|
||||||
var username = "";
|
|
||||||
if (chance.bool()) {
|
|
||||||
username += chance.first();
|
|
||||||
if (chance.bool()) {
|
|
||||||
username += chance.last();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
username += chance.word({syllables: 3})
|
|
||||||
}
|
|
||||||
if (chance.bool()) {
|
|
||||||
username += chance.integer({min: 30, max: 99});
|
|
||||||
}
|
|
||||||
return username.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
var app = angular.module('app', ["ngSanitize"]);
|
|
||||||
|
|
||||||
// http://stackoverflow.com/a/20033625/79461
|
|
||||||
app.filter("nl2br", function () {
|
|
||||||
return function (data) {
|
|
||||||
if (!data) return data;
|
|
||||||
return data.replace(/\r?\n/g, '<br/>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// http://stackoverflow.com/a/20033625/79461
|
|
||||||
app.filter("autolink", function () {
|
|
||||||
return function (data) {
|
|
||||||
return Autolinker.link(data, {truncate: {length: 50, location: 'middle', newWindow: true}});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.controller('MailboxController', ["$interval", "$http", "$log", function ($interval, $http, $log) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.backend_url = backend_url;
|
|
||||||
|
|
||||||
self.updateUsername = function (username) {
|
|
||||||
username = username.replace(/[@].*$/, ''); // remove part after "@"
|
|
||||||
if (self.username !== username) {
|
|
||||||
// changed
|
|
||||||
self.username = username;
|
|
||||||
hasher.setHash(self.username);
|
|
||||||
|
|
||||||
if (self.username.length > 0) {
|
|
||||||
self.address = self.username; // use username until real address has been loaded
|
|
||||||
self.updateMails();
|
|
||||||
} else {
|
|
||||||
self.randomize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.inputFieldUsername = self.username;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
self.randomize = function () {
|
|
||||||
self.updateUsername(generateRandomUsername());
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
self.onHashChange = function (hash) {
|
|
||||||
self.updateUsername(hash);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.$onInit = function () {
|
|
||||||
hasher.changed.add(self.onHashChange.bind(self));
|
|
||||||
hasher.initialized.add(self.onHashChange.bind(self)); //add initialized listener (to grab initial value in case it is already set)
|
|
||||||
hasher.init(); //initialize hasher (start listening for history changes)
|
|
||||||
|
|
||||||
$interval(self.updateMails, reload_interval_ms);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.updateMails = function () {
|
|
||||||
if (self.username) {
|
|
||||||
self.loadEmailsAsync(self.username);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.loadEmailsAsync = function (username) {
|
|
||||||
$http.get(backend_url, {params: {username: username}})
|
|
||||||
.then(function successCallback(response) {
|
|
||||||
if (response.data.mails) {
|
|
||||||
self.error = null;
|
|
||||||
self.mails = response.data.mails;
|
|
||||||
self.address = response.data.address;
|
|
||||||
self.username = response.data.username;
|
|
||||||
if (self.inputFieldUsername === self.username) {
|
|
||||||
self.inputFieldUsername = self.address;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.error = {
|
|
||||||
title: "JSON_ERROR",
|
|
||||||
desc: "The JSON from the response can not be read.",
|
|
||||||
detail: response
|
|
||||||
};
|
|
||||||
$log.error(response);
|
|
||||||
}
|
|
||||||
}, function errorCallback(response) {
|
|
||||||
$log.error(response, this);
|
|
||||||
self.error = {
|
|
||||||
title: "HTTP_ERROR",
|
|
||||||
desc: "There is a problem with loading the data. (HTTP_ERROR).",
|
|
||||||
detail: response
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
self.deleteMail = function (mail, index) {
|
|
||||||
// instantly remove from frontend.
|
|
||||||
self.mails.splice(index, 1);
|
|
||||||
|
|
||||||
// remove on backend.
|
|
||||||
var firstTo = Object.keys(mail.to)[0];
|
|
||||||
$http.get(backend_url, {params: {username: firstTo, delete_email_id: mail.id}})
|
|
||||||
.then(
|
|
||||||
function successCallback(response) {
|
|
||||||
self.updateMails();
|
|
||||||
},
|
|
||||||
function errorCallback(response) {
|
|
||||||
$log.error(response, this);
|
|
||||||
self.error = {
|
|
||||||
title: "HTTP_ERROR",
|
|
||||||
desc: "There is a problem with deleting the mail. (HTTP_ERROR).",
|
|
||||||
detail: response
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initial load
|
|
||||||
self.updateMails()
|
|
||||||
}]);
|
|
|
@ -3,22 +3,20 @@
|
||||||
// set your time zone:
|
// set your time zone:
|
||||||
date_default_timezone_set('Europe/Paris');
|
date_default_timezone_set('Europe/Paris');
|
||||||
|
|
||||||
// enable while testing:
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
// enable in production:
|
// enable in production:
|
||||||
// error_reporting(0);
|
error_reporting(0);
|
||||||
|
|
||||||
|
// enable while testing:
|
||||||
|
//error_reporting(E_ALL);
|
||||||
|
|
||||||
// configure this option if you want to allow requests from clients from other domains:
|
|
||||||
// see https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
|
||||||
// header("Access-Control-Allow-Origin: *");
|
|
||||||
|
|
||||||
// Change IMAP settings (check SSL flags on http://php.net/manual/en/function.imap-open.php)
|
// Change IMAP settings (check SSL flags on http://php.net/manual/en/function.imap-open.php)
|
||||||
$config['imap']['url'] = '{example.com/imap/ssl}INBOX';
|
$config['imap']['url'] = '{imap.example.com/imap/ssl}INBOX';
|
||||||
$config['imap']['username'] = "test";
|
$config['imap']['username'] = "myuser";
|
||||||
$config['imap']['password'] = "test";
|
$config['imap']['password'] = "mypassword";
|
||||||
|
|
||||||
// email domain, usually different from imap hostname:
|
// email domains, usually different from imap hostname:
|
||||||
$config['mailHostname'] = "example.com";
|
$config['domains'] = array('mydomain.com', 'example.com');
|
||||||
|
|
||||||
// When to delete old messages?
|
// When to delete old messages?
|
||||||
$config['delete_messages_older_than'] = '30 days ago';
|
$config['delete_messages_older_than'] = '30 days ago';
|
150
src/index.html
150
src/index.html
|
@ -1,150 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="de" ng-app="app" ng-strict-di>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Mailbox</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
||||||
<meta name="description" content="Mailbox">
|
|
||||||
<link rel="shortcut icon" href="favicon.gif" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" href="client-libs/style.css">
|
|
||||||
<link rel="stylesheet" href="client-libs/spinner.css">
|
|
||||||
<link rel="stylesheet" href="client-libs/angular-stickyfill-0.1.0/angular-stickyfill.css">
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"
|
|
||||||
integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div ng-controller="MailboxController as $ctrl" ng-cloak>
|
|
||||||
<header>
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<form ng-submit="$ctrl.updateUsername($ctrl.inputFieldUsername)">
|
|
||||||
|
|
||||||
<small id="emailHelp" class="form-text text-muted">
|
|
||||||
You have <span class="tag tag-pill tag-default">{{$ctrl.mails.length}}</span> mails in your
|
|
||||||
mailbox:
|
|
||||||
</small>
|
|
||||||
|
|
||||||
<div class="form-group row">
|
|
||||||
<div class="col-sm-8">
|
|
||||||
|
|
||||||
<input id="inputFieldUsername" ng-model="$ctrl.inputFieldUsername"
|
|
||||||
placeholder="new username"
|
|
||||||
type="text" class="form-control form-control-lg" onclick="this.select()"/>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<button id="openRandomButton" ng-click="$ctrl.randomize()" type="button"
|
|
||||||
class="btn btn-outline-primary">open random
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div class="container min-height">
|
|
||||||
<div ng-if="$ctrl.error" class="alert alert-danger" role="alert">
|
|
||||||
<p><strong>Sorry, there was a problem. </strong></p>
|
|
||||||
<p> {{$ctrl.error.desc}} </p>
|
|
||||||
<div>
|
|
||||||
<pre>{{$ctrl.error.detail|json}}</pre>
|
|
||||||
</div>
|
|
||||||
<p> If you are the developer you might want to check the developer tools console of your web
|
|
||||||
browser and your php error logs. </p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="$ctrl.username && $ctrl.mails.length == 0">
|
|
||||||
<div class="card waiting-screen">
|
|
||||||
<div class="card-block">
|
|
||||||
<p class="lead">Your mailbox <strong>{{$ctrl.address}}</strong> is ready. </p>
|
|
||||||
<p>Emails will appear here automatically. They will be deleted after 30 days.</p>
|
|
||||||
<div class="spinner">
|
|
||||||
<div class="rect1"></div>
|
|
||||||
<div class="rect2"></div>
|
|
||||||
<div class="rect3"></div>
|
|
||||||
<div class="rect4"></div>
|
|
||||||
<div class="rect5"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ng-if="$ctrl.username" ng-repeat="mail in $ctrl.mails | orderBy:'-date' track by $index"
|
|
||||||
class="email-table">
|
|
||||||
|
|
||||||
<div class="card email">
|
|
||||||
<div class="card-block header-shadow sticky-header" ec-stickyfill ng-init="htmlTabActive=false">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<h3 class="card-title">{{mail.subject}}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4 text-right">
|
|
||||||
<form class="form-inline float-xs-right">
|
|
||||||
|
|
||||||
<button ng-show="htmlTabActive" class="btn btn-outline-info btn-sm "
|
|
||||||
ng-click="htmlTabActive=false">show text
|
|
||||||
</button>
|
|
||||||
<button ng-show="mail.textHtml && !htmlTabActive"
|
|
||||||
class="btn btn-outline-info btn-sm"
|
|
||||||
ng-click="htmlTabActive=true">show html
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<a role="button" class="btn btn-sm btn-outline-primary "
|
|
||||||
href="{{$ctrl.backend_url}}?download_email_id={{mail.id}}&username={{$ctrl.username}}"
|
|
||||||
download="true">Download
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<button ng-click="$ctrl.deleteMail(mail, $index)" type="button"
|
|
||||||
class="btn btn-sm btn-outline-danger">Delete
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<h6 class="card-subtitle mt-1 text-muted">{{mail.fromName}}
|
|
||||||
<{{mail.fromAddress}}></h6>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<h6 class="card-subtitle mt-1 text-muted" style="text-align: right">{{mail.date}}</h6>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-block">
|
|
||||||
<h6 class="card-subtitle text-muted">To: {{mail.toString}}</h6>
|
|
||||||
<h6 ng-if="mail.cc" ng-repeat="(address,name) in mail.cc" class="card-subtitle text-muted">CC:
|
|
||||||
{{address}}</h6>
|
|
||||||
|
|
||||||
<div class="mt-2 card-text">
|
|
||||||
<div ng-if="!htmlTabActive" ng-bind-html="mail.textPlain | nl2br | autolink "></div>
|
|
||||||
<div ng-if="htmlTabActive" ng-bind-html="mail.textHtml"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<p>Powered by <a href="https://github.com/synox/disposable-mailbox"><strong>synox/disposable-mailbox</strong></a>
|
|
||||||
| <a href="https://github.com/synox/disposable-mailbox"><span class="octicon octicon-mark-github"></span> Fork
|
|
||||||
me on github</a></p>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-sanitize.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/autolinker/1.2.0/Autolinker.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/chance/1.0.4/chance.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/stickyfill/1.1.4/stickyfill.min.js"></script>
|
|
||||||
<script src="client-libs/angular-stickyfill-0.1.0/angular-stickyfill.js"></script>
|
|
||||||
<script src="client-libs/index.js"></script>
|
|
||||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/js-signals/1.0.0/js-signals.js"></script>
|
|
||||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/hasher/1.2.0/hasher.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
240
src/index.php
Normal file
240
src/index.php
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
<?php
|
||||||
|
require_once('backend.php');
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($_GET['random'])) {
|
||||||
|
redirect_to_random($config['domains']);
|
||||||
|
die();
|
||||||
|
} elseif (isset($_GET['username']) && isset($_GET['domain'])) {
|
||||||
|
$username = filter_input(INPUT_GET, 'username', FILTER_SANITIZE_EMAIL);
|
||||||
|
$domain = filter_input(INPUT_GET, 'domain', FILTER_SANITIZE_EMAIL);
|
||||||
|
header("location: ?address=$username@$domain");
|
||||||
|
die();
|
||||||
|
} elseif (!isset($_GET['address'])) {
|
||||||
|
error(400, 'invalid action');
|
||||||
|
} else {
|
||||||
|
// perform common validation:
|
||||||
|
$address = filter_input(INPUT_GET, 'address', FILTER_SANITIZE_EMAIL);
|
||||||
|
$username = _clean_username($address);
|
||||||
|
$userDomain = _clean_domain($address);
|
||||||
|
if (strlen($address) === 0) {
|
||||||
|
error(400, 'invalid username');
|
||||||
|
}
|
||||||
|
if (strlen($userDomain) === 0 || !in_array($userDomain, $config['domains'])) {
|
||||||
|
error(400, 'invalid domain');
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple router:
|
||||||
|
if (isset($_GET['download_email_id'])) {
|
||||||
|
download_email($_GET['download_email_id'], $address);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
if (isset($_GET['delete_email_id'])) {
|
||||||
|
$delete_email_id = filter_input(INPUT_GET, 'delete_email_id', FILTER_SANITIZE_NUMBER_INT);
|
||||||
|
delete_email($delete_email_id, $address);
|
||||||
|
}
|
||||||
|
// print emails:
|
||||||
|
$emails = get_emails($address);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Mailbox <?php echo $address ?></title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<link rel="stylesheet" href="spinner.css">
|
||||||
|
<script src="turbolinks.js"></script>
|
||||||
|
<meta name="turbolinks-cache-control" content="no-preview">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// https://stackoverflow.com/a/44353026
|
||||||
|
var reloadWithTurbolinks = (function () {
|
||||||
|
var scrollPosition;
|
||||||
|
|
||||||
|
function reload() {
|
||||||
|
scrollPosition = [window.scrollX, window.scrollY];
|
||||||
|
Turbolinks.visit(window.location.toString(), {action: 'replace'})
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('turbolinks:load', function () {
|
||||||
|
if (scrollPosition) {
|
||||||
|
window.scrollTo.apply(window, scrollPosition);
|
||||||
|
scrollPosition = null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return reload
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
setInterval(function () {
|
||||||
|
reloadWithTurbolinks();
|
||||||
|
}, 10000)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body data-turbolinks="false">
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<div class="container">
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
change username:
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<form action="?" method="get">
|
||||||
|
<div class="form-group row">
|
||||||
|
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input id="username" data-turbolinks-permanent class="form-control form-control-lg" name="username"
|
||||||
|
value="<?php echo $username ?>">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<select id="domain" data-turbolinks-permanent class="form-control form-control-lg" name="domain">
|
||||||
|
<?php
|
||||||
|
foreach ($config['domains'] as $domain) {
|
||||||
|
$selected = $domain === $userDomain ? ' selected ' : '';
|
||||||
|
print "<option value='$domain' $selected>@$domain</option>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-3 random-column">
|
||||||
|
<span>or </span>
|
||||||
|
<a role="button" href="?random=true" class="btn btn-outline-primary">generate random
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="container min-height">
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if (empty($emails)) {
|
||||||
|
?>
|
||||||
|
<div>
|
||||||
|
<div class="card waiting-screen">
|
||||||
|
<div class="card-block">
|
||||||
|
<p class="lead">Your mailbox <strong
|
||||||
|
><?php echo $address ?></strong> is ready. </p>
|
||||||
|
<p>Emails will appear here automatically. They will be deleted after 30
|
||||||
|
days.</p>
|
||||||
|
<div class="spinner">
|
||||||
|
<div class="rect1"></div>
|
||||||
|
<div class="rect2"></div>
|
||||||
|
<div class="rect3"></div>
|
||||||
|
<div class="rect4"></div>
|
||||||
|
<div class="rect5"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="email-table">
|
||||||
|
|
||||||
|
<div class="card email">
|
||||||
|
<div class="card-block header-shadow sticky-header">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<h3 class="card-title">
|
||||||
|
<?php echo filter_var($email->subject, FILTER_SANITIZE_SPECIAL_CHARS); ?>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 text-right">
|
||||||
|
<form class="form-inline float-xs-right">
|
||||||
|
|
||||||
|
<!-- <button class="btn btn-outline-info btn-sm">show html-->
|
||||||
|
<!-- </button>-->
|
||||||
|
|
||||||
|
<a class="btn btn-sm btn-outline-primary " download="true"
|
||||||
|
role="button"
|
||||||
|
href="?download_email_id=<?php echo filter_var($email->id, FILTER_VALIDATE_INT); ?>&address=<?php echo $address ?>">Download
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- <button class="btn btn-sm btn-outline-danger" type="button">-->
|
||||||
|
<!-- Delete-->
|
||||||
|
<!-- </button>-->
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<h6 class="card-subtitle mt-1 text-muted">
|
||||||
|
<?php
|
||||||
|
echo filter_var($email->fromName, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
echo ' <';
|
||||||
|
echo filter_var($email->fromAddress, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
echo '>';
|
||||||
|
?>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<h6 class="card-subtitle mt-1 text-muted"
|
||||||
|
style="text-align: right">
|
||||||
|
<?php echo filter_var($email->date, FILTER_SANITIZE_SPECIAL_CHARS); ?>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-block">
|
||||||
|
<h6 class="card-subtitle text-muted">
|
||||||
|
To: <?php echo filter_var($email->toString, FILTER_SANITIZE_SPECIAL_CHARS); ?></h6>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
foreach ($email->cc as $cc) {
|
||||||
|
print "<h6 class='card-subtitle text-muted'>CC: " . filter_var($cc, FILTER_SANITIZE_SPECIAL_CHARS) . "</h6>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mt-2 card-text">
|
||||||
|
<!-- TODO: switch between html and plaintext -->
|
||||||
|
<div>
|
||||||
|
<!-- TODO: applyAutolink
|
||||||
|
TODO: applyNewlines -->
|
||||||
|
<?php $text = filter_var($email->textPlain, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
echo str_replace(' ', '<br />', $text);
|
||||||
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div *ngIf="htmlTabActive">
|
||||||
|
<!-- TODO: stripHtml(mail.textHtml) -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -19,22 +19,18 @@ div.min-height {
|
||||||
|
|
||||||
header {
|
header {
|
||||||
background-color: #D9E2E9;
|
background-color: #D9E2E9;
|
||||||
/* leave some space on top */
|
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#openRandomButton {
|
#openRandomButton {
|
||||||
/* center vertically */
|
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.email-table > .email {
|
.email-table > .email {
|
||||||
border-top: 5px solid #7C96AB;
|
border-top: 5px solid #7C96AB;
|
||||||
|
|
||||||
/* idea: card shadow arround:
|
|
||||||
see https://blog.alexdevero.com/mastering-card-design-with-bootstrap-4/
|
|
||||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-shadow {
|
.header-shadow {
|
||||||
|
@ -47,7 +43,6 @@ header {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.waiting-screen {
|
.waiting-screen {
|
||||||
padding: 40px 15px;
|
padding: 40px 15px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -57,3 +52,7 @@ div.min-height {
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.random-column {
|
||||||
|
border-left: 1px dashed #333;
|
||||||
|
|
||||||
|
}
|
6
src/turbolinks.js
Normal file
6
src/turbolinks.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue