letölthető script

.HU domain ellenőrzés host névből

Szükségem volt arra, hogy egy adott string-ről eldöntsem, érvényes magyar (.hu) domain név-e avagy sem. Utánajártam a témának, és kiderítettem, hogy melyek a pontos szabályok .hu domain regisztrációja esetében:

  • A domain név csak angol kisbetűket (a-z), számokat (0-9), kötőjelet (-) és magyar ékezetes kisebetűket (áéíóöőúüű) tartalmazhat.
  • Az ékezetes domain neveknek létezik, egy un. IDN formával alakja, amely kódolt formában tartalmaz az ékezetes karaktereket. Ezek a domain nevek xn-- karakterekkel kezdődnek.
  • Nem lehet rövidebb 2 karakternél, és nem lehet hosszabb 40 karakternél. (Nincs infó, hogy az ékezetes karakterekkel kell-e számolni, vagy az eltérő hosszúságú IDN.)
  • Másodszintű közdomaineket (pl. info.hu) nem lehet regisztrálni, de eléjük egy harmadszintű nevet lehet regisztrálni (pl. edgarpe.info.hu érvényes lenne.)
  • Vannak védett nevek (pl. www) amelyeket nem lehet regisztrálni sem másod, sem harmad szinten. A net és az internet, bár védett neveke, a net.hu és az internet.hu domainek mégis lézetnek.
  • Vannak zárolt domain nevek (pl. turizmus.hu), amelyeket nem lehet regisztrálni.
  • Jelenleg (2012. március 12.) 31 darab másodszintű közdomain van, 28 darab védett név, és 28 darab zárolt név.

Több időt töltöttem el a szabályok kinyomozásával és a php nyelvű teszt függvény megírásával, mint amennyit szerettem volna.

Megosztom itt is, ha valakinek spórolok vele pár órát, már megérte.

Végül kicsit többet oldottam meg, mint egy ellenőrző: a függvény bemenete egy hostnév, visszatérési értéke a hostból kinyert domain név, vagy FALSE, ha nem érvényes a név. Utóbbi esetben a referencia szerínt átadott második $error paraméterben meg is mondja, mi volt a gond. Tehát pl. a valami.edgarpe.hu bemenetre, a válasz edgarpe.hu lesz, a valami.info.edgarpe.hu bemenetre pedig edgarpe.info.hu lesz a válasz.

Kizárólag .HU TLD domain nevekre működik.

Végül egy tipp: ha nem host név áll rendelkezésre, hanem teljes URL akkor érdemes lehet használni a parse_url php-s függvény átírását is, ritkábban hasal el rossz bemenetekre.

Itt a kód, de letölthető formmában is megvan az oldal alján:

<?php
/**
 * .HU domain név ellenörző. Ellenörzi, hogy egy adott host érvényes magyar .hu
 * domain-hez tartozik-e.
 *
 * Figyelembe vett szabályok:
 * - a domain név hossza (min 2, max 40 karakter)
 * - érvényes karakterek (a-z, 0-9, -, áéíóöőúüű)
 * - kötőjel szabályok a név elején, közepén és végén
 * - másodszintű közdomainek
 * - védett nevek
 * - zárolt nevek
 *
 * @param $host
 *   Host név, amely feltételezhetően egy érvényes .hu domain névhez tartozik.
 * @param $error
 *   Referencia szerint átadva. Hibaüzenet, ha a host nem .hu domain része.
 * @return
 *   A domain név (string) amihez a $host tartozik, vagy FALSE ha téves.
 */
function domain_from_host($host, &$error = NULL) {
 
$level2 = array(
   
'co', 'info', 'org', 'priv', 'sport', 'tm', '2000', 'agrar',
   
'bolt', 'casino', 'city', 'erotica', 'erotika', 'film', 'forum', 'games',
   
'hotel', 'ingatlan', 'jogasz', 'konyvelo', 'lakas', 'media', 'news',
   
'reklam', 'sex', 'shop', 'suli', 'szex', 'tozsde', 'utazas', 'video',
  );
 
 
$protected = array(
   
'ac', 'arpa', 'biz', 'co', 'com', 'dns', 'email', 'e-mail', 'firm', 'ftp',
   
'gov', 'ind', 'info', 'internet', 'iskola', 'mail', 'mx', 'net', 'nom',
   
'ns', 'nui', 'org', 'pp', 'priv', 'sport', 'tm', 'web', 'www',
  );

 
$closed = array(
   
'accomodation.hu', 'aruhaz.hu', 'aukcio.hu', 'auto.hu', 'befektetes.hu',
   
'bor.hu', 'broker.hu', 'business.hu', 'butor.hu', 'cash.hu', 'credit.hu',
   
'house.hu', 'jacht.hu', 'kamat.hu', 'konyv.hu', 'magazin.hu', 'oras.hu',
   
'orszag.hu', 'pc.hu', 'search.hu', 'szabadido.hu', 'telek.hu', 'trade.hu',
   
'translation.hu', 'travel.hu', 'turizmus.hu', 'voip.hu', 'vpn.hu',
  );
 
 
$error = NULL;

  if (
preg_match('/^[a-z0-9\\á\é\í\ó\ö\ő\ú\ü\ű\-\.]+$/', $host) !== 1) {
   
$error = 'Invalid characters';
    return
FALSE;
  }
 
 
$parts = array_reverse(explode('.', $host));
 
  if (
count($parts) < 2) {
   
$error = 'Invalid format.';
    return
FALSE;
  }
 
  if (
$parts[0] !== 'hu') {
   
$error = 'Not .hu domain.';
    return
FALSE;
  }
 
  if (
in_array($parts[1] .'.'. $parts[0], $closed)) {
   
$error = 'Closed domain.';
    return
FALSE;
  }
 
  if (
in_array($parts[1], $level2)) {
    if (isset(
$parts[2])) {
     
$name = $parts[2];
     
$suffix = '.'. $parts[1] .'.hu';
    }
    else {
     
$error = 'Second level domain.';
      return
FALSE;
    }
  }
  else {
   
$name = $parts[1];
   
$suffix = '.hu';
  }
 
  if (
in_array($name, $protected) && !in_array($name . $suffix, array('internet.hu', 'net.hu'))) {
   
$error = 'Protected name.';
    return
FALSE;
  }
 
  if (
mb_strlen($name) < 2) {
   
$error = 'Domain too short.';
    return
FALSE;
  }

  if (
mb_strlen($name) > 40) {
   
$error = 'Domain too long.';
    return
FALSE;
  }
 
  if (
$name[0] == '-') {
   
$error = 'Name stats with \'-\' character.';
    return
FALSE;
  }
 
  if (
$name[strlen($name) - 1] == '-') {
   
$error = 'Name ends with \'-\' character.';
    return
FALSE;
  }
 
 
$before_needle = strstr($name, '--', TRUE);
  if (
$before_needle === 'xn') {
   
$before_needle = strstr(substr($name, 4), '--');
  }
  if (
$before_needle !== FALSE) {
   
$error = 'Double minus (\'--\') character found.';
    return
FALSE;
  }
 
  return
$name . $suffix;
}
?>

Ha hibákért és a használatból eredő károkért nem vállalok felelősséget. Viszont ha megírjátok a hibát kommentben, akkor javítani, ha tudom.

Batch API: Sok feladat elvégzése Drupalban AJAX-szal.

Egy újabb Drupal gyrostipp következik.

Amikor bekapcsolunk egy új nyelvet, vagy verziófrissítés utána, amikor meglátogatjuk az update.php-t, azt láthatjuk, hogy megjelenik egy teljes képernyős AJAX-os állapotjelző sáv, un. „progress bar”. Azért hasznos ez az AJAX-os megoldás, mert ha a feladatok elvégzése 30 másodpercnél tovább tartana, a php szkript futása megszakadhat, és a feladatok elvégzése félúton megállna. Így viszont a Drupal gondoskodik, hogy néhány másodperc futás utána, a háttérben, egy új http lekérés indul, ezzel kiküszöbölve a 30 másodperces kolátot.

Most mogmutatom, hogyan tudunk mi is ilyet készíteni. Drupal-al ez is nagyon egyszerű:

A funkció lelke a Drupal magban a batch.inc-ben van elrejtve, és nekünk mindössze egyetlen függvényt, a batch_set()-et, és annak paraméterezését kell ismernünk. Ez a függvény egyetlen paramétert vár, egy tömböt. A tömbben meg lehet adni a feladatlista nevét, az elvégzendő feladatokat, amelyek php callback függvények és paramétereik, illetve a befejezéskor meghívandó callback függvény.

A példakód ilyen egyszerű:

<?php
  $batch
= array(
   
'title' => t('Helló batch feladatok'),  // a feladatlista címe
   
'operations' => array(),                // feladatok tömbje
   
'finished' => 'hellobatch_finished',    // befejezéskor meghívandó
 
);
 
  for (
$i=0; $i<$form_state['values']['jobs']; $i++) {
   
$operation = array(
     
'hellobatch_job',   // egy feladat callback fg.
     
array($i),          // és paraméterei
   
);
   
$batch['operations'][] = $operation;
  }
 
batch_set($batch);
?>

Ha mindezt egy form_submit függvényben hívjuk meg, nem is kell mást tennünk, azonnal elindul a feladatok elvégzése. Ha form submit-on kívűl akarjuk használni, akkor még a batch_process() függvényre lesz szükségünk.

További infó angulul az API oldalon.

A példamodul kódját csatolttam, próbáljátok ki!

parse_url() alternatíva

HTML-ből kiszedett url-eket dolgoztam volna fel, de a PHP beépített parse_url() függvénye egy warning kíséretében elszáll, ha relatív url-eket adunk meg.

Szintén nem tetszenek neki az olyan URI-k, mint pl. a mailto: vagy ftp://

Írtam egy függvényt, ami úgy dolgozza fel az URL-eket és URI-kat, hogy

  • soha nem száll el warning-al
  • jól kezeli a relatív URL-eket
  • teljes értékű helyettesítője a php parse_url()-nek

Itt a kód, illetve a post végén egy linken le is tölthető. Bárki bármilyen hibát talál, jelezze a hozzászólásoknál, hogy javíthassam.

<?php
function parse_url_relative($url, $component = NULL){
 
$full_rx = '!^
    (?P<scheme>[a-z][a-z0-9\+\-\.]*):/*         # scheme
    (?:(?P<user>[^:@]*)(?::(?P<pass>[^@]*))?@)? # user and password
    (?P<host>[^/\?\#:]*)                        # host
    (?::(?P<port>[0-9]+))?                      # port
    (?P<path>[^\?\#]*)                          # path
    (?:\?(?P<query>[^\#]*))?                    # query
    (?:\#(?P<fragment>.*))?                     # fragment
  $!ix'
;

 
$path_rx = '!^
    (?P<path>[^\?\#]*)                          # path
    (?:\?(?P<query>[^\#]*))?                    # query
    (?:\#(?P<fragment>.*))?                     # fragment
  $!ix'
;

  if (!
preg_match($full_rx, $url, $m)) {
   
preg_match($path_rx, $url, $m);
  }

 
$return = array(
   
'scheme'    => isset($m['scheme'])    ? $m['scheme']    : NULL,
   
'user'      => isset($m['user'])      ? $m['user']      : NULL,
   
'pass'      => isset($m['pass'])      ? $m['pass']      : NULL,
   
'host'      => isset($m['host'])      ? $m['host']      : NULL,
   
'port'      => isset($m['port'])      ? $m['port']      : NULL,
   
'path'      => isset($m['path'])      ? $m['path']      : '',
   
'query'     => isset($m['query'])     ? $m['query']     : '',
   
'fragment'  => isset($m['fragment'])  ? $m['fragment']  : '',
  );

  switch (
$component) {
    case
NULL:
      return
$return;
    case
PHP_URL_SCHEME:
      return
$return['scheme'];
    case
PHP_URL_HOST:
      return
$return['host'];
    case
PHP_URL_PORT:
      return
$return['port'];
    case
PHP_URL_USER:
      return
$return['user'];
    case
PHP_URL_PASS:
      return
$return['pass'];
    case
PHP_URL_PATH:
      return
$return['path'];
    case
PHP_URL_QUERY:
      return
$return['query'];
    case
PHP_URL_FRAGMENT:
      return
$return['fragment'];
  }
}
?>

Karakter alapú szöveg-összehasonlítás PHP-vel

Tartalom

Bevezető

Készülve a csütörtöki diplomavédésre, megnéztem a bíráló által feltett kérdéseket. Diplomatervem egy adatbázis séma alapú PHP kódgenerátor. (Később majd írok erről egy részletes post-ot.) A bíráló egyik kérdése volt, hogy a generált forráskód hány százalékát kell átírni egy valós környezetben.

Ez egy nagyon jó kérdés, bennem is felmerült már. Forráskód bázis rendelkezésre áll, úgyhogy van kód amin meg lehet mérni. Első ötlet lehet a diff parancs. De ebben az esetben problémás lehet, hogy a diff soronként vizsgálja a forráskódot. Ez két dolog miatt gond:

  • A generált kódban vannak felesleges blokkok, amelyeket nem töröltem hanem a // jelekkel kommenteztem ki.
  • Minden táblához létrejön egy konfigurációs fájl, amelynek az a célja, hogy testreszabáskor módosítsák. Minden sorát!

Ez a két eset nagyon gyakori, ezért a soronként összehasonlítás alapján megítélni a forráskód-generátor jóságát félrevezető lenne.

Egy karakter alapú összehasonlítás ennél sokkal pontosabb információt adna. Kicsit kutattam az interneten és találtam egy megoldást, amit kicsit átírva született a lenti kód.

Karakter alapú szöveg-összehasonlító PHP szkript

A lenti szkript definiál egy CharDiff osztályt, amit a PEAR Text_Diff csomagban található Text_MappedDiff osztályból öröklődik. A Text_MappedDiff pedig a Text_Diff-ből öröklődik, tehát a lenti osztály egyben Text_Diff osztályú is. Ez azért jó, mert a fent említett csomagban van jónéhány renderer, amelyekkel különböző szabványos patch kimeneteket lehet generálni.

De szerettem volna vizualizálni is a dolgot, ezért az osztály része egy render metódus ami HTML kimenetet ad, és grafikusan ábrázolja a a különbséget a két szöveg között.

Eredeti kód: www.hawkee.com

Íme a kód, CharDiff.php:

<?php
/**
 * Karakter alapú szövegösszehasonlító
 * -----------------------------------
 * Használat:
 * $text1 = 'árvíztűrő tükörfúrógép';
 * $text2 = 'árvíztörő tükörfúrógép';
 *
 * $diff = new CharDiff($text1, $text2);
 *
 * $diff->render();
 */

require_once 'Text/Diff.php';

class
CharDiff extends Text_MappedDiff {

  function
CharDiff ($text_src, $text_tgt) {

   
$chars_src = str_split($text_src, 1);
   
$chars_tgt = str_split($text_tgt, 1);

   
$chars_src_mapped = $chars_src;
   
$chars_tgt_mapped = $chars_tgt;

     
parent::Text_MappedDiff($chars_src, $chars_tgt, $chars_src_mapped, $chars_tgt_mapped);
  }

  function
getStat() {
   
$stat = array();

   
$stat['copy']  = 0;
   
$stat['add']  = 0;
   
$stat['del']  = 0;
   
$stat['change']  = 0;
   
$stat['change-del']  = 0;
   
$stat['change-add']  = 0;

    foreach(
$this->getDiff() as $op) {
      if (
is_a($op, 'Text_Diff_Op_copy')) $stat['copy'] += $op->norig();
      if (
is_a($op, 'Text_Diff_Op_delete')) $stat['del'] += $op->norig();
      if (
is_a($op, 'Text_Diff_Op_add')) $stat['add'] += $op->nfinal();
      if (
is_a($op, 'Text_Diff_Op_change')) { $stat['change-del'] += $op->norig(); $stat['change-add'] += $op->nfinal(); }
    }

    return
$stat;
  }

  function
render($color_delete = 'red', $color_add = 'green') {
    foreach (
$this->getDiff() as $op) {
      if (
is_a(&$op,'Text_Diff_Op_copy')) {
        echo
$this->_implode($op->final);
      }
      elseif (
is_a(&$op,'Text_Diff_Op_delete')) {
        echo
'<span style="background-color: ', $color_delete, ';">', $this->_implode($op->orig), '</span>';
      }
      elseif (
is_a(&$op,'Text_Diff_Op_add')) {
        echo
'<span style="background-color: ', $color_add.';">', $this->_implode($op->final), '</span>';
      }
      elseif (
is_a(&$op,'Text_Diff_Op_change')) {
        echo
'<span style="background-color: ', $color_delete.';">', $this->_implode($op->orig), '</span>';
        echo
'<span style="background-color: ', $color_add.';">', $this->_implode($op->final), '</span>';
      }
    }
   
    return
$return;
  }

  function
_implode($chars) {
    return
nl2br( implode('', array_map( array($this, '_htmlFilter'), $chars) ) );
  }

 
// used with array_map
 
function _htmlFilter($text) {
    return
$text = str_replace( array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $text);
  }

}
?>

A feneti kód letölthető itt: [attachment:CharDiff.php.txt=CharDiff.php]

Az osztály használata:

<?php
  $text1
= 'árvíztűrő tükörfúrógép';
 
$text2 = 'árvíztörő tükörfúrógép';

 
$diff = new CharDiff($text1, $text2);

 
$diff->render();
?>

Remélem lesz aki hasznosnak találja majd.

Feliratkozás RSS - letölthető script csatornájára