2018. november 15., csütörtök

Google Chrome & sw.js & localhost & SSL

Röviden:
  • localhost https kapcsolat alatt self signed ssl tanusítvány van beállítva.
  • service worker sw.js regisztráció hibába ütközik tanusítvány probléma
  • "An SSL certificate error occurred when fetching the script." és társai console hibaüzenetek.
  • a google szerint a "unsafely-treat-insecure-origin-as-secure" chrom flag majd biztos megoldja.
  • nem jön össze több kombóban sem
  • De hoppá, hoppá, az újabb Chrome böngészőkben van erre egy elegánsabb megoldás
  • Tehát: chrome://flags/#allow-insecure-localhost

2018. szeptember 17., hétfő

PHP: "/public" eltávolítása az URL-ből

Ez a probléma általában előjön az én esetemben.

A relativitás híve vagyok. Egy oldal menjen az éles tárhelyen a gyökérből, vagy akár egy almappából a fejlesztés helyén.
Persze a mai trendek nagyon tolják a "csinálj mindennek egy-egy virtualhost-ot" jellegű tutorialokat, és minden legyen bebetonozva.

Általában fel-felbukkan egy-egy olyan oldal, ahol még a képek, és más erőforrások elérését is "/" karakterrel kezdik, hogy az biztosan az oldalhoz tartozó document root szerver beállítástól legyen értelmezve. Hogy ez miért jó? Még nem tudom. De az is megtörténhet, hogy egyszer, előbb-utóbb a szemem elé akad egy cikk, amely elmagyarázza, hogy így fontos másodperceket is meg lehet spórolni a nagy látogatottságú és/vagy nagy erőforrás igényű oldalaknál.
Hasonló volt a helyzet a CDN tárhelyekről hosztolt harmadik féltől származó javascript, css, és font csomagok esetén is. Valóban gyorsabb lenne a kiszolgálás, ha a legtöbb dolgot külföldi CDN-ről menne. (cdnjs, jsdelivr, stb..), de mint később néhány cikk rávilágított, hogy a magyarországi hálózati rendszer felépítése éppen az ellenkező hatást váltja ki, és tovább tarthat több esetben a kiszolgálás, mint ha azt közvetlenül az oldal tárhelyéről szolgálódna ki, vagy egy másik magyarországi CDN tárhelyről.
No mindegy is.

Visszatérve a címben lévő témához.

Általában belefutok a fenti problémába. Főleg, ha olyan tárhely hozzáférést kapok, ami közvetlenül a document root mappára mutat és nem lehet egy szinttel feljebb másolni.
Persze itt most jöhet a következő jó gondolat: "miért nem másolja ki az ember fia az egész public mappát az oldal gyökerébe?" Mert néhány kísérlet talán ki lehet találni néhány fontos és létező útvonalat, amit nem kellene látni. "De erre meg ott van a .htaccess, vagy egy-egy üres index.html, stb..."

A vitát lehet folytatni még egy darabig. Ez vitathatatlan.

Szóval a lenti linken egy kis kód részlet érhető el, amely az URL-ben lévő "/public" karakter sorozatot távolítja el az URL-ből átirányítással:
https://gist.github.com/racztiborzoltan/e6ab85c3b54d7e8bc0d482ec3cee17e0

Szép napot!

2018. szeptember 5., szerda

2018. szeptember 4., kedd

Kategória fa lekérdezése 3 szintig egy SQL utasításban

Optimalizálni kellett egy nagyobb kategória fának a lekérdezését, hogy egy SQL utasítással lehessen lekérdezni az összes szükséges információt, így ne legyen annyiszor megszólítva az adatbáziskezelő.

Természetesen már korábban is belefutottam a problémába, de eddig nem publikáltam semmit.

Tehát álljon itt egy SQL utasítás megjegyzésekkel:

--
-- SQL utasítás, amely faszerkezetbe rendezett kategóriákat tud
-- maximum 3 szintig listázni.
-- Az eredményt lineárisan bejárva a programozási nyelvben is lehet 
-- egy több dimenziós tömböt felépíteni, mert nem fog előfordulni,
-- hogy a felsőbb szint esetleg később jönne a listában!
--
SELECT

-- TODO: További oszlopokat szabadon hozzáadni!

-- Az első táblában lévő információkra van szükségünk:
c_1.id

-- Ebben az oszlopban a kategória hierarchiának megfelelően fordított
-- sorrendben kerülnek "," karakterrel összefűzésre
-- Az eredményhalmaz feldolgozása során nagy segítséget nyújthat egy többdimenziós
-- szerkezet összeállításához.
, CONCAT_WS(",", c_1.id, c_2.id, c_3.id) AS category_hierarchy

-- Ez az oszlop azt számolja ki, hogy hányadik kategória szinten 
-- fog elhelyezkedni az adott sorban lévő "c_1"-es kategória
, 1 + LENGTH(CONCAT_WS(",", c_1.id, c_2.id, c_3.id))
  - LENGTH( REPLACE ( CONCAT_WS(",", c_1.id, c_2.id, c_3.id), ",", "") )  AS level_number
-- A listázott kategóriához hozzácsatoljuk, ha lehetséges a szülő kategóriáját,
-- és a szülő kategóriához hozzácsatoljuk annak a szülőjét is, ha lehetséges:
FROM category_tree AS c_1
LEFT JOIN category_tree AS c_2 ON c_1.parent_id = c_2.id
LEFT JOIN category_tree AS c_3 ON c_2.parent_id = c_3.id
WHERE
-- Ez csak apróság, de általában mindenhol jelen van egy "Látható-e a kategória"
-- típusú oszlop információ, ami alapján csak a publikus kategóriák lesznek listázva
-- Természetesen láthatóság nem csak a levél kategóriára lesz ellenőrizve.
-- Ha a szülő nem látható, akkor nem lenne értelme listázni a benne lévő 
-- elemeket
(
c_1.status = 1
-- A 2. és 3. csatolt táblában az IS NULL is szükséges, mert nem biztos
-- hogy minden sorhoz lehetett további szülő és szülő-szülő kategóriát 
-- csatolni. Ekkor ugye a LEFT JOIN miatt ezek a mezők NULL értékúek lesznek.
AND (c_2.status IS NULL OR c_2.status = 1)
AND (c_3.status IS NULL OR c_3.status = 1)
)
-- Ez a feltétel azt köti ki, hogy az 1. vagy a 2. vagy 3. szintnek a gyökérben
-- kell végződnie, amelynek már nincs szülője
AND (
c_1.parent_id IS NULL
OR c_2.parent_id IS NULL
OR c_3.parent_id IS NULL
)
ORDER BY
-- Szükséges növekvő sorban a szint számnak megfelelő sorba rendezni az 
-- eredményeket, hogy az eredményhalmaz lineáris feldolgozása során ne legyen
-- olyan kategória, amelynek a szülője még nem került volna feldolgozásra.
level_number ASC
-- Érdemes valamilyen egyértelmű sorszámozást tartalmazó oszlop alapján 
-- még rendezni az eredményeket:
, c_1.sequence_number ASC





2018. augusztus 31., péntek

Laravel: cookie beállítása, hogy elérhető is legyen azonnal a response objektum megszületése előtt

Kóstolgatom a Laravel PHP keretrendszert.

Egyik problémám a címben némileg hosszan és hanyagul lett megfogalmazva.

Mert ugye van itt ez a:
Cookie::queue('key', 'value', 5);
Amivel a response létrejötte előtt lehet olyan cookie-kat definiálva, ami majd automatikusan hozzá lesz dobva a response objektumhoz, ha az már létezni tetszik. (nagyjából)

De nekem az kellett, hogy ha én azt mondom sablonosan, hogy
cookie_beallitasa($name, $value);
akkor a függvény meghívását követő sorban már ki tudjam adni a
\Cookie::get($name);
metódus hívást és éppen az előbb beállított $value értéket kapjam.

Erre jutottam:
$request->cookies->set('name', 'value');
echo \Cookie::get('name'); // output: 'value'

Hova is kellett ez nekem:
Egy middleware osztályba, ami a request handler lefutása előtt kellett, hogy beállítson néhány dolgot a cookie értékek közé.

Ui.: Valószínű, hogy van erre egy sokkal frappánsabb és egyszerűbb megoldás, de egy kevés google keresgélés után mindig a ::queue() metódusba futottam, de az éppen nem oldja meg a problémámat.

2018. augusztus 30., csütörtök

PHP_INI_SCAN_DIR környezeti változó a PHP-ban

Mire is jó ez a PHP_INI_SCAN_DIR?

Ha ez a környezeti változó be van állítva a PHP futási környezetében, akkor az ebben tárolt útvonalon megpróbál minden *.ini fájlt betölteni, amellyel felüldefiniálhatóak a korábban már beolvasott "php.ini" beállítások.

Bővebben angolul a PHP dokumentációjában: http://php.net/manual/en/configuration.file.php#configuration.file.scan

FONTOS:
Ne tévesszük össze a futtatható php parancssori kapcsolói közül a "-c <path>|<file>" lehetőséggel. Ez utóbbi arra való, hogy ha érvényes fájlra vagy könyvtárra mutat, akkor a php beállításokat tartalmazó fájlokat onnan próbálja beolvasni. Ha a -c kapcsoló nem mutat érvényes fájlra vagy könyvtárra, akkor a PHP az alapértelmezett helyek valamelyikén keres majd megfelelő ini állományt.

Ui.: A fenti változó nagyon hasznosnak fog bizonyulni a saját kis webszerveren további pofozgatásában, mert már meguntam, hogy az egyik PHP verzióban egy kicsit másképpen vannak beállítva olyan általános értékek, mint például a feltölthető maximális fájlméret (max_upload_filesize) vagy a POST kérések maximális mérete (post_max_size) és hasonlók.

2018. augusztus 24., péntek

FtpUse - Windows alatt FTP felcsatolása meghajtóként

Az FtpUse egy aprócska program, amit feltelepítve parancssorosan lehet meghajtó betűjelhez rendelni egy-egy ftp kapcsolatot.

Szerintem nagyon egyszerű a használata.

A programról bővebben a https://www.ferrobackup.com/map-ftp-as-disk.html URL címen.

Ui.: az első próbálkozások után nem igazán tudtam hordozható állapotra varázsolni, de ez valószínűleg a Dokan meghajtók miatt lehet.
A Dokan könyvtárról bővebben itt: https://dokan-dev.github.io/

2018. augusztus 14., kedd

Reguláris kifejezés: Az URL abszolút hivatkozás?

Reguláris kifejezéssel általában így szoktam tesztelni, hogy egy URL abszolút hivatkozás-e:
^((https?):)?//

A fenti kifejezés illeszkedik az alábbiakra:
http://www.example.com
https://www.example.com
//www.example.com
http://example.com
https://example.com
//example.com

De nem illeszkedik például az alábbiakra:
assets/page.js
/relative-from-document-root/assets/page.js


Magyarázat:
  • A szöveg elejére nézi az illeszkedést a "^" karakter
  • A szöveg elején 0 vagy egyszer szerepelhet a "https" karaktersorozat, amelyben az "s" karakter 0 vagy egyszer fordulható elő a "http" szöveg után
  • Az illeszkedő "http" vagy "https" szöveget követni kell egy ":" karakternek
  • Ha van illeszkedő "http:" vagy "https:" karaktersorozat a szöveg elején, akkor ezek 0 vagy egyszer fordulhatnak elő ("((https?):)?")
  • Ha volt protokoll illeszkedés, akkor utána legyen egy "//" karaktersorozat, vagy protokoll nélküli feltüntetés esetén a szöveg azonnal a "//" karaktersorozattal kezdődjön

www kiegészítés

Ha szükséges a "www." előtagra való illeszkedés is, akkor a fenti kifejezés kibővül az alábbira:
^((https?):)?//(www.)?


Használjátok egészséggel!

XSLT - minden másolása

Jó dolog ez az XSLT!

Például ha azt szeretnénk, hogy egy XML forrásból minden elem át legyen másolva a generált tartalomba, akkor a következő egyszerű és rekurzív XSLT sablont is lehet definiálnunk:

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>

Röviden: 
A fenti szabály illeszkedik minden xml csomópontra és xml attributumra. Ha illeszkedik, akkor ugye 
lefut. 

Működése: az illeszkedő elemet (legyen az éppen aktuálisan egy csomópont, vagy attributum) másold át a cél dokumentumba. A másolás után alkalmazd újra az összes definiált XSLT sablon szabályt az aktuális csomóponton belül közvetlenül minden gyerek csomópontra, vagy attributumra.

Zseniális?

Update: egy angol nyelvű bővebb cikk a fentiekről: http://www.usingxml.com/Transforms/XslIdentity

2018. augusztus 12., vasárnap

PHP "arg_separator.output" beállítási lehetőség legyen inkább "&"

Előtörténet:

2018-at írunk, és van egy honlap, amely egy mondjuk valamennyire régebbecske tárhelyen foglal helyet. Kapott egy kis felújítást és a későbbiekben is fog kapni ezt-azt. Mondjuk, hogy ez egy olyan kis hobby oldalam. Elvállaltam.
A tárhely PHP 5.3.10. Nem mai darab, ezt azt hiszem ki lehet jelenteni.

Saját localhost-on szintén egy PHP 5.3.29 lett beállítva az oldal fejlesztéséhez. Lent minden tökéletes volt. Felmásoltam.

A probléma ott kezdődött, hogy egy oldalon volt egy átirányítás, ha nem voltak bizonyos url paraméterek a kérésben. A szükséges default url paraméterekkel készítettem egy url, és azt header() függvénnyel ki is lett küldve, ami lent tökéletesen működött.
A szükséges plusz paraméterek a http_build_query() függvénnyel lettek hozzáfűzve az új URL-hez, és egy Location: header kíséretében ki lett küldve az éterbe.

De az átirányított url-ben a "&" paraméterek helyett "&amp;" szerepelt. Ez így nem kóser, és elkezdtem kutatni.

A hibakeresés addig mindent rendben talált, hogy a http_build_query() függvény még helyes kimenetet ad.

Talán a header() függvényben van valami turpisság, illetve annak valamilyen beállítása?

...

Végül odáig fajult a dolog, hogy összehasonlítottam a lenti és a fenti phpinfo() kimenetét, azon belül a konfiuráiciós értékek listáját. Először tovább siklott a tekintetem, de utána ráakadtam a címben említett "arg_separator.output" beállítási lehetőségre, ami vajon mi volt az éles helyen? Hát persze, hogy "&amp;" és lent nálam pedig az "&" érték.

Mivel az éles tárhelyen nem férek hozzá a php.ini beállításokhoz közvetlenül, de szerencsére az ini_set() függvény nem lett letiltva, ezért ezen keresztül lett orvosolva a hiba.

Milyen kis apróság, és közel 1 órás nagyon izgalmas hibakereséssel gazdagította (?) az életemet.

2018. augusztus 2., csütörtök

Apache beállítás - FcgidInitialEnv

Előtörténet:
Röviden: elkezdtem magamnak egy saját kis fejlesztői webszervert összerakni már évek óta folyamatosan, amiről valószínűleg több bejegyzés is fog születni, mert érdemesnek tartom megosztani néhány kódrészletet.

Az apache-ban (amiből egyenlőre csak egy példányt tudok futtatni, de ez nem lesz mindig így) egy újabb lehetőséget szerettem volna megvalósítani, ami sikerült is, mások segítségével. Köszönet Nagy Gergőnek és közvetve Dankó Dávidnak, aki Nagy Gergőnek segített ezt magvalósítani.
pl.: "localhost/php55" és a "localhost/php56" alatt ugyanaz a root mappa kerüljön kiszolgálásra, de eltérő PHP verziók segítségével. Ezt sikerült is megoldani, amihez soft linkekre volt szükségem, valamint néhány fcgi php folyamat definiálására.
(Majd néhány kódmorzsát megosztok később.)
A dolog eddig úgy látszott, hogy tökéletesen működik.

DE! Egy új projektet kellett beindítani localhost alatt, de panaszkodott, hogy nem tudja írni a session mentéséhez mappát. Kis kutakodás után rájöttem, hogy a php.ini-ben a session.save_path beállításnál használt környezeti változómat nem látja a fcgi-ban indított PHP-m. Normál apache PHP modulként működött a dolog.

Rövid kerekített 5 perces keresgélés után meg is lett a megoldás. Az apache httpd.conf fájlban az fcgi definiálásakor szükséges volt megadni FcgidInitialEnv beállítást is.

Dokumentáció:
https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidinitialenv


Ui.: Mire képes az "apache és php fejlesztői csomagom"?
- egyetlen apache verzió
- több php verzió (5.3.x, 5.4.x, 5.5.x, 5.6.x, 7.0.x, 7.1.x, 7.2.x, 7.3.x), amelyből mindig a legújabb patch verziók vannak használva. A frissítés manuálisan történik, ami általában 3-4 percet vesz igénybe.
- "localhost" url kiszolgálása a apache_php_module segítségével, amely az alapértelmezetten beállított php verziót veszi alapul és annak megfelelőn állítja be az apache-ot is. Ennek a megváltoztatásához egy fájlban egy érték átállítására és az apache újraindítására van szükség.
- "localhost:80xx" különböző portokon különböző PHP verziók szolgálják ki a php fájlokat
- "localhost/phpxx" url-eken történő kiszolgálás különböző php verziókkal úgy, hogy mindegyik ilyen url ugyanazt a mappát mutatja, mint a "localhost" url.

Ui. 2.: Erről a kis saját fejlesztő csomagomról még írkálok ezt-azt. Egyetlen paranccsal indítható apache, több mysql, több php, composer, nginx, nodejs, stb..., és időnként van benne fejlődés, fejlesztés is, mint például, ahogy most is.

2018. július 26., csütörtök

restart (ismét)

Azt hiszem, hogy megpróbálom újrakezdeni ezt a blog dolgot.
A korábbi bejegyzések is megmaradnak.

Majd meglátjuk.

De az is megtörténhet, hogy keresek és találok blogger.com alternatívát.