// In src/Model/Table/UsersTable.php public function validatePasswords($validator) { $validator->add('password2', 'no-misspelling' , [ 'rule' => [ 'compareWith' , 'password' ], 'message' => 'Hasła nie są takie same.' , ]); ... return $validator; }
CakePHP – loadInto() – lazy loading
Dołączenie modeli do pobranego już zasobu
$articles = $this->Articles->find()->all(); $withMore = $this->Articles->loadInto($articles, ['Comments', 'Users']);
TinyMCE config
Plik konfiguracyjny tinyMce
CakePHP – CounterCache
Przechowuje w tabeli ilość rekordów podrzędnych (dzieci). Definiowany jest na tabeli podrzędnej ( belongsTo() ). Tabela nadrzędna musi mieć kolumnę typu int (np. comment_count)
class CommentsTable extends Table { public function initialize(array $config) { $this->belongsTo('Articles'); $this->addBehavior('CounterCache' , [ 'Articles' => [ 'comment_count' ] ]); } }
Można zastosować CounterCache w powiązaniach belongsToMany() tylko z opcją through. Wówczas behaviour definiuje się w tabeli łączącej gdyż posiada powiązania belongsTo().
Wprowadzenie warunku – zlicza tylko komentarze bez spamu
$this->addBehavior('CounterCache' , [ 'Articles' => [ 'comment_count' => [ 'conditions' => [ 'Comments.spam' => false] ] ] ]);
CakePHP – Tree behaviour
Obsługuje złożone struktury hierarchiczne. Zapewnia wiele metod dostępu, prezentacji, generowania list, ścieżek i manipulacji elementami.
Kolumny wymagane w tabeli
parent_id lft rght level - przechowuje poziom (opcjonalna) model - lub country własna kolumna dla opcji skope (opcjonalna)
Chrome flags
Izolowanie procesorów renderowania stron – bezpieczeństwo
chrome://flags Strict site isolation Site isolation trial opt-out
chrome://flags/#enable-site-per-process
CakePHP – find(’list’)
class ArticlesTable extends Table
{
public function initialize(array $config)
{
$this->setDisplayField('title');
}
}
$query = $articles->find('list' , [ 'keyField' => 'slug' , 'valueField' => 'title' 'groupField' => 'author_id' ]); $data = $query->toArray();
$query = $articles->find('list' , [ 'keyField' => 'id' , 'valueField' => 'author.name' ])->contain([ 'Authors' ]);
cakePHP hydration
$query->enableHydration(false);
CakePHP – entity properties
Dostępne do zmiany przez formularz
class User extends Entity
{
protected $_accessible = [
'id' => false,
'*' => true
]
}
$article->accessible('title' , false); $article->set($properties, [ 'guard' => false]);
Właściwości wirtualne uwzgl. w konwersji na array/json
class User extends Entity
{
protected $_virtual = [ 'full_name' ];
}
$user->virtualProperties([ 'full_name' , 'is_admin' ]);
Nie będą exportowane do formatu array/json
class User extends Entity
{
protected $_hidden = [ 'password' ];
}
$user->hiddenProperties([ 'password' , 'recovery_question' ]);
CakePHP – badanie właściwości
$article->has('title' ); // czy jest i czy ma wartość $article->isEmpty('title' ); // czy jest pusta $article->hasValue('title' ); // czy ma wartość $article->isNew(); // nie zapisany jeszcze w bazie $article->isDirty('title' ); // czy zmieniono title $article->comments[] = $newComment; $article->setDirty('comments' , true); // ustaw - zmieniono $dirtyFields = $entity->getDirty(); // pobierz wszystkie falgi $article->clean(); // wyczyść wszystkie flagi dirty
$entity->unsetProperty('name'); $user->unsetProperty('beers'); // user belongsToMany beers $user->has('beers'); // false // Aby znowu mieć dostęp - ładujemy ręcznie $user= $this->Programmers->loadInto($user, ['Beers']);
CakePHP – virtual property
Definiowanie właściwości wirtualnej (nie będzie zapisana do bazy)
protected function _getFullName() { return $this->_properties[ 'first_name' ] . ' ' . $this->_properties[ 'last_name' ]; }
echo $user->full_name;
CakePHP – druga baza danych
Cake – korzystanie z drugiej bazy danych
namespace App\Model\Table; use Cake\ORM\Table; class ArticlesTable extends Table { public static function defaultConnectionName() { return 'replica_db' ; } }
cakephp 3 – używanie daty
$user['age'] = $user['birth_date']->diff(new \DateTime)->y;
$this->request
$controllerName = $this->request->getParam('controller' ); $params = $this->request->getAttribute('params' ); $passedArgs = $this->request->getParam('pass' ); // URL is /posts/index?page=1&sort=title $page = $this->request->getQuery('page' ); $query = $this->request->getQueryParams(); // Input with a name 'MyModel[title]' $title = $this->request->getData('MyModel.title' ); $host = $this->request->env('HTTP_HOST' ); $env = $this->request->getServerParams(); // /subdir/articles/edit/1?page=1 $here = $request->getRequestTarget(); $base = $request->getAttribute('base'); // /subdir $base = $request->getAttribute('webroot'); // /subdir/ $jsonData = $this->request->input('json_decode' ); $data = $this->request->input('Cake\Utility\Xml::build' , [ 'return' => 'domdocument' ]); $this->request->is('post') $this->request->is('ajax') // X-Requested-With = XMLHttpRequest $this->request->is('json') // application/xml lub text/xml .json (ext) $userName = $this->request->session() ->read('Auth.User.name' );
$request->domain(); $request->subdomains(); $request->host(); $request->getMethod(); $this->request->allowMethod([ 'post' , 'delete']);
WP przeniesienie hostingu
1. Przeniesienie kodu – FTP
2. Kopia bazy danych – takie same: charset, collate
3. Zmiany parametrów nowej bazy danych
# nano wp-config.php dbname dbuser dbpass dbhost
4. Zmiany domeny w tabeli wp_options:
mysql> select * from wp_options where option_id=1 or option_id=2; +-----------+-------------+-----------------+----------+ | option_id | option_name | option_value | autoload | +-----------+-------------+-----------------+----------+ | 1 | siteurl | https://old.pl | yes | | 2 | home | https://old.pl | yes | +-----------+-------------+-----------------+----------+ mysql> update wp_options set option_value='https://new.pl' where option_value='https://old.pl'
5. Opcjonalnie można zmienić wpisy w tabeli wp_posts. Wszystkie tabele nowej bazy danych można przeszukać ze względu na nazwę starej domeny.
mysql – dostęp z sieci – GRANT
User z dostępem z sieci
mysql> GRANT SELECT,INSERT,UPDATE,DELETE, EXECUTE ON dbname.* TO 'username'@'%' IDENTIFIED BY 'passwd';
php7.0 extentions
Pakiety do pracy z CakePHP3, Moodle3
# dpkg -l | grep php . ii libapache2-mod-php7.0 ii php-common ii php7.0 ii php7.0-cli ii php7.0-common ii php7.0-curl ii php7.0-gd ii php7.0-intl ii php7.0-json ii php7.0-mbstring ii php7.0-mcrypt ii php7.0-mysql ii php7.0-opcache ii php7.0-readline ii php7.0-soap ii php7.0-sqlite3 ii php7.0-xml ii php7.0-xmlrpc ii php7.0-zip
reCaptcha
Klient – Kod HTML
-- head <script src='https://www.google.com/recaptcha/api.js'></script> -- form - przycisk reCaptcha <div class="g-recaptcha" data-sitekey="62LczhlYUAAAAAAYW6nsSPsXJ-mulLH6w7TxFH4Pa"></div>
Serwer – kod PHP
if($_POST['send']) { $response = $_POST['g-recaptcha-response']; if($response) { $url = "https://www.google.com/recaptcha/api/siteverify"; $secret = "62LczhlYUAAAAADTnGOz8GRl9c66Rwn4GDSVsChAg"; $remoteip = $_SERVER['REMOTE_ADDR']; $params = [ 'secret' => $secret, 'remoteip' => $remoteip, 'response' => $response ]; $post_params = http_build_query($params); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params); $response = curl_exec($ch); curl_close($ch); $resp_tab = json_decode($response, true); if( $resp_tab['success'] ) { //Przetwarzanie i wysłanie formularza ... $info = "Formularz wysłany"; } else { $info = "Nieprawidłowa weryfikacja testu w Google. Kod błęd: " .$resp_tab['error-codes'][0]; } } else { $info = "Błędny wybór lub nie wypełniłeś chptcha."; } $smarty->assign('info', $info); }
Ajax – PHP – rezerwacje
Przykład obsługi rezerwacji po obu stronach – klient serwer
Metasploit instalacja debian
https://www.darkoperator.com/installing-metasploit-in-ubunt/
https://www.webupd8.org/2014/03/how-to-install-oracle-java-8-in-debian.html
Debian instalacja node
# apt-get install build-essential # apt-get install curl libcurl3 php7.0 php7.0-curl # curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash - # apt-get install -y nodejs
# node -v v9.4.0 # npm -v 5.6.0
scroll_behavour
https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior
Płynne przewijanie zawartości pojemnika
<nav> <a href="#page-1">1</a> <a href="#page-2">2</a> <a href="#page-3">3</a> </nav> <scroll-container> <scroll-page id="page-1">1</scroll-page> <scroll-page id="page-2">2</scroll-page> <scroll-page id="page-3">3</scroll-page> </scroll-container>
a { display: inline-block; width: 50px; text-decoration: none; } nav, scroll-container { display: block; margin: 0 auto; text-align: center; } nav { width: 339px; padding: 5px; border: 1px solid black; } scroll-container { display: block; width: 350px; height: 200px; overflow-y: scroll; scroll-behavior: smooth; } scroll-page { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 5em; }
Przeglądarki – offline
Application Cache
chrome://appcache-internals
Service Workers
chrome://inspect/#service-workers chrome://serviceworker-internals/ Firefox: about:config dom.serviceWorkers.enabled = true
Babel
# mkdir babel_test # cd babel_test && npm init
package name: (babel_test) version: (1.0.0) description: entry point: (index.js) test command: echo "Error: no test specified" && exit 1 git repository: keywords: author: license: (ISC) About to write to D:\JS\nodejs\babel_test\package.json: { "name": "babel_test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } Is this ok? (yes)
Instalacja babel
# npm install --save-dev babel-cli
Podmienić w package.json właściwość scripts:
"scripts": { "build": "babel src -d lib" }
Aktualizacja npm
# npm install npm@latest -g
# npm -v # node -v
Apache SSL
# cd /etc/apache2 # a2enmod ssl # a2ensite default-ssl # systemctl reload apache2 # mkdir /etc/apache2/ssl # openssl req -x509 -nodes -days 1825 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt # chmod 600 /etc/apache2/ssl/* # nano /etc/apache2/sites-enabled/default-ssl.conf
default-ssl.conf
<IfModule mod_ssl.c> <VirtualHost _default_:443> ServerAdmin webmaster@localhost ServerName bambino.pl:443 DocumentRoot /var/www/html/bambino/webroot . . . SSLEngine on . . . SSLCertificateFile /etc/apache2/ssl/apache.crt SSLCertificateKeyFile /etc/apache2/ssl/apache.key
# service apache2 reload # openssl s_client -connect intranet.int:443
X-Frame-Options
Informuje przeglądarkę, że żadna strona z tym nagłówkiem nie może być osadzona w iframe.
X-Frame-Options: DENY
<header> <frame-options policy="SAMEORIGIN" /> </header>
X-XSS-Protection
Co ma zrobić przeglądarka gdy rozpozna atak XSS. Niektóre przeglądarki mają wbudowane filtrowanie XSS reflected.
X-XSS-Protection: 1; mode=block
<header> <xss-protection block="false"/> </header>
HTTP security headers
Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000 ; includeSubDomains X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
HTTP Content Security Policy
Nagłówek odpowiedzi. Serwer informuje przeglądarkę które skrypty z jego domeny mogą być dołączone
Content-Security-Policy: <policy-directive>; <policy-directive<
// header Content-Security-Policy: default-src https: Content-Security-Policy: default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none' // meta tag <meta http-equiv="Content-Security-Policy" content="default-src https:">
Dyrektywy:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy