Strona główna » Informatyka

Kategoria: Informatyka

Programowanie a oderwanie od podstaw

Niedawno czytałem wątek na Facebooku, w którym ktoś zapytał specjalistów od informatyki czy byliby w stanie sami zbudować od podstaw te różne urządzenia, z którymi pracują. Odpowiedzi były różne. Poczyniliśmy tak duży postęp techniczny, że niektórym się wydaje, że owszem, zrobią hurtownię danych, ale już pojedynczy tranzystor to kosmiczna technologia. Innymi słowy, specjalizacja, abstrakcja i miniaturyzacja oderwały niektórych profesjonalistów od źródeł ich zawodów. I nie ma w tym nic dziwnego, taki jest porządek rzeczy.

W programowaniu też widać zjawisko pewnego oderwania od podstaw, ale ma ono związek z dopasowaniem narzędzi pracy do umysłu pracującego. Weźmy na przykład kolorowanie składni. Jest tak powszechne i tak pomocne, że jej wyłączenie wprawić niektórych może w zakłopotanie, może wywołać poczucie zagubienia. Tymczasem dawniej często tak się pisało kod. I w dalszym ciągu w wielu przypadkach kod przychodzi pisać po dawnemu, gdy trzeba coś na szybko zmienić na serwerze z linii poleceń a tam czeka nas niedokonfigurowany edytor vi o niecodziennych skrótach klawiszowych.

Warto chyba przypomnieć, że programowanie nie tylko jest możliwe, ale jest całkiem wydajne w takich warunkach jak zwykły notepad. Czarno-białe litery, brak obsługi tabulatorów, brak podpowiedzi, brak podręcznego drzewa plików. To tylko przyzwyczajenia się zmieniły.

Jest to ważne także i dlatego, że wiele osób bardzo poważnie taktuje dzisiaj temat doboru narzędzi. Preferują pewne określone IDE czy określony program do administracji bazą danych oraz mają wyobrażenie takie, że te programy są niebywale złożone i koniecznie trzeba stosować te szczególnie wybrane.

Tymczasem ani nie ma takiej konieczności, ani te programy nie są szczytem złożoności. Wiele z nich można napisać samemu i w życiu programisty przychodzi taki moment, że zmuszony okolicznościami tworzy on np.:

  • Własne IDE
  • Własne webowe IDE
  • Własnego klienta SQL do administacji bazą
  • Własnego klienta GIT
  • Własnego klienta SSH, SCP, FTP
  • Własnego shella

Ze zdumieniem można wówczas odkryć, że podstawowe funkcjonalności tego oprogramowania da się wykonać w zaskakująco małych ilościach linii kodu. Te zaś przyrastają dopiero wtedy, gdy chce się wygładzić i wyspecjalizować określone obszary.

(W dawniejszych czasach nie było to rzadkością chcieć pisać własny system operacyjny, bo ludzie dzięki powszechności dyskietek i możliwości podglądu kodu BIOS-u mieli wiedzę o bootsectorach, systemach plików, zarządzaniu pamięcią. Dzisiaj to już jest wiedza nieco zapomniana.)

Użycie certyfikatów Let’s Encrypt do wielu serwisów na zwykłym hostingu

Wprowadzenie

Kiedyś pisałem o tym jak można dla serwisów umieszczonych na zwykłych hostingach WWW używać darmowych certyfikatów Let’s Encrypt. Procedura jest jednak żmudna, nudna i trzeba ją powtarzać co kilka miesięcy, co dla kogoś, kto utrzymuje wiele serwisów a nie tylko jeden, jest dosyć nużące. Jeżeli jednak wciąż nie chcemy iść w kierunku zakupu płatnych certyfikatów, to rozwiązaniem jest uruchomienie tzw. reverse proxy na tanim serwerze wirtualnym. Wyjaśnijmy sobie to po kolei.

Najtańsze płatne certyfikaty są obecnie na rynku za około 10 zł. Jeżeli ktoś opiekuje się 10 serwisami internetowymi, które są umiejscowione ma zwykłym hostingu na którym nie można w sposób zautomatyzowany korzystać z darmowych certyfikatów, to musi wydać 100 zł rocznie na certyfikaty. Nie jest to duża kwota a kłopotu jest troszeczkę mniej.

Innym rozwiązaniem jest wykupienie na rok taniego serwera wirtualnego. Ich oferta w Internecie jest spora a mówimy tutaj o wersji naprawdę bardzo ubogiej, bo wymagającej 1 procesora wirtualnego, około 5 GB miejsca dyskowego, od 512 do 1024 MB RAM. Można takie kupić płacąc za rok około 110 zł, czyli wiele więcej niż za certyfikaty – a stajemy się bogatsi o serwer VPS!

Przygotowanie VPSa

W moim przypadku zamówiłem serwer z systemem operacyjnym CentOS 8, aby móc na nim uruchomić skrypt konfiguracyjny, który rozwijam i którego kod jest w repozytorium na GitHub:

curl -s -L http://grzegorzkowalski.pl/install/ | bash

Skrypt będzie wykonywał wiele działań i zada kilka pytań. Odpowiedź „Y” należy udzielić na te:

  • Enable Apache [default port 80 and 443] ? [y/N]
  • Change timezone to Europe/Warsaw? [y/N]
  • Enable FirewallD ? [y/N]

Po tym wszystkim dostaniemy serwer z Apache’m i mnogością różnych użytecznych narzędzi (m.in. PHP 7.4, Python 2/3, NPM, Node.js, Composer, Certbot, wget, GIT). Nas interesuje głównie Apache, którego możemy skonfigurować w tryb reverse proxy.

Tworzymy sobie nowy plik konfiguracyjny do tego celu i jeżeli nasz hosting ma adres 123.123.123.123 to piszemy tak.:

vi /etc/httpd/conf.d/moje_proxy.conf

Wypełniamy go treścią:

<VirtualHost *:80>
ServerName grzegorzkowalski.pl
ServerAlias www.grzegorzkowalski.pl
ServerAlias kolejnyserwis.pl
ServerAlias innyserwis.pl
ServerAlias jeszczeinny.pl
ServerAlias itakdalej.pl
# ...
ServerAlias az_do_ostateniego.pl

DocumentRoot "/var/www/html/proxy"
ServerAdmin grzegorz.adam.kowalski@outlook.com

<Directory "/var/www/html/proxy">
DirectoryIndex index.php
AllowOverride All
Require all granted
</Directory>

ProxyPreserveHost On
ProxyPass / http://123.123.123.123:80/
ProxyPassReverse / http://123.123.123.123:80/
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RequestHeader set X-Forwarded-SSL expr=%{HTTPS}
</VirtualHost>

W pliku konfiguracyjnym odwołujemy się do folderu, którego jeszcze nie ma, więc warto go stworzyć:

mkdir /var/www/html/proxy

Teraz w panelu konfiguracyjnym hostingu znajdźmy edycję stref DNS i zmieńmy we wszystkich domenach wskazanych w powyższym pliku konfiguracyjnym numer IP przypisany do tzw. rekordu „A” na adres IP naszego serwera VPS.

Gdy to wszystko jest gotowe, zresetujmy Apache na serwerze wirtualnym, aby nowa konfiguracja weszła w życie. W zależności od systemu może to wymagać trochę innego polecenia, na moim CentOS wygląda to tak:

service httpd restart

No i teraz przed nami zagadnienie wygenerowania certyfikatów. W systemie powinien już być zainstalowany i gotowy do użycia skrypt:

certbot-auto

Należy postępować zgodnie z pytaniami, które będą pojawiać się na ekranie a wynikiem będą wygenerowane certyfikaty, lekko rozszerzony plik konfiguracyjny Apache, który wcześniej stworzyliśmy oraz dodatkowo zostanie stworzony drugi plik konfiguracyjny przeznaczony tylko dla ruchu szyfrowanego na porcie 443.

Gdy WordPress odmawia współpracy

Teraz proxy jest już sprawne, certyfikaty również są zrobione. To,co jeszcze może nas spotkać to zaskoczenie, gdy np. nasz serwis oparty o WordPress odmówi posłuszeństwa a przeglądarka internetowa zwróci komunikat „Too many redirects” czyli „zbyt wiele przekierowań”.

Jak się okazuje, twórcy WordPressa zaszyli jedną ważną informację w instrukcji do tego systemu. W pliku wp-config.php należy ręcznie dopisać w dowolnym miejscu dwie linie kodu:

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
$_SERVER['HTTPS']='on';

Debugowanie zbyt wielu przekierowań

Jeżeli problem „Too many redirects” pojawia się pomimo odpowiedniej konfiguracji takiego czy innego systemu, warto zbadać zjawisko pomocniczym skryptem (jest to zmodyfikowana wersja tego skryptu):

#!/bin/bash
echo
for domain in $@; do
  echo --------------------
  echo $domain
  echo --------------------
  curl -sILk $domain | egrep 'HTTP|Loc|X-Redirect-By: ' | sed 's/Loc/ -> Loc/g'
  echo
done

Skrypt używamy np. tak:

skrypt-do-przekierowan.sh grzegorzkowalski.pl

W wyniku skryptu zobaczymy serię nagłówków HTTP wskazujących na typ przekierowania, docelowe miejsce przekierowania oraz kto zlecił przekierowanie. W przypadku np. WordPressa wyświetli się np. „WordPress 7.4.3”. Jest to informacja, że przyczyna problemu leży nie w konfiguracji Apache, nie w jakimś zabłąkanym pliku .htaccess na hostingu, ale np. w pluginie WordPressowym do obsługi HTTPS albo właśnie w braku wpisu w wp-config.php.

Dekodowanie base64 o zmienionym alfabecie

Serwis pewnej znanej państwowej instytucji zwraca sam dla siebie dane za pomocą interfejsu typu API REST, ale zwraca jest w postaci kodowanej. Wynik zaczyna się mniej więcej tak:

{"d":"enc!331aa1bb!45!3!!49!32!50!381ab1a7!45y25!45yy91b9y23yy4y1y1a1y231a2!391a1y...."}

No i zagadaka – co to jest i jak to odczytać? Skoro przeglądarka potrafi, to znaczy to, że gdzieś w skryptach strony jest dekoder. No rzeczywiście znajdujemy skrypt, który jednakże zdaje się być sam sobie również zaszyfrowany, jego początek wygląda tak:

eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c])}}return p}('o a=["\b\d\b","\b\b\i","\b\b\j","\b\b\l","\b\b\s","\b\b\N","\b\b\m","\b\b\D","\b\b\z","\b\i\B","\b\i\b","\b\i\i","\b\i\j","\b\i\l","\b\i\s","\b\i\N","\b\i\m","\b\i\D","\b\i\z","\b\j\B","\e\j\e","\e\j\i","\e\j\j","\e\j\l","\e\j\s","\e\j\N","\e\j\m","\e\j\D","\e\j\z","\e\l\B","\e\l\e"

Początek „function packed” jest charakterystyczny dla standardowych zaciemniaczy kodu. Da się to względnie odszyfrować, jest wiele deszyfratorów online, np. https://freeseotool.org/javascript-unpacker.

Po deszyfracji wciąż nie jest łatwo. Zmienne mają dziwaczne nazwy, a tablice mają zwartości zapisane za pomocą kodów szesnastkowych. To ostatnie to drobiazg, bo jeżeli mam taką dziwną tablicę…

var _0xeae2=["\x79\x31\x79","\x79\x79\x32","\x79\x79\x33","\x79\x79\x34","\x79\x79\x35","\x79\x79\x36","\x79\x79\x37","\x79\x79\x38","\x79\x79\x39","\x79\x32\x30","\x79\x32\x79","\x79\x32\x32","\x79\x32\x33","\x79\x32\x34","\x79\x32\x35","\x79\x32\x36","\x79\x32\x37","\x79\x32\x38","\x79\x32\x39","\x79\x33\x30","\x21\x33\x21","\x21\x33\x32","\x21\x33\x33","\x21\x33\x34","\x21\x33\x35","\x21\x33\x36","\x21\x33\x37","\x21\x33\x38"

…to wystarczy są wrzucić w przeglądarkowy console.log i dostanę zwrot danych w ludzkiej postaci:

["y1y", "yy2", "yy3", "yy4", "yy5", "yy6", "yy7", "yy8", "yy9", "y20", "y2y", "y22", "y23", "y24", "y25", "y26", "y27", "y28", "y29", "y30", "!3!", "!32", "!33",

Hmm, znowu jakiś kod? Może, aczkolwiek jeżeli wrócimy do pierwotnej zaszyfrowanej wiadomości, to dostrzeżemy, że składała się właśnie z takich elementów. Wygląda więc to na jakiegoś rodzaju alfabet. W alfabecie nie ma jedynie początkowego trzyliterowego „enc”, które widać w danych zawracanych przez API, więc pewnie to jakiś taki rozpoznawczy ciąg znaków (zapewne pochodzący od „encoded” – zakodowany).

Wróćmy jednak na chwilę do nazw. Nazwy zmiennych są kodowane, ale nazwy funkcji nie – są takie jak kiedyś były. Znajdujemy w skrypcie cztery:

  • tajemnicza funkcja „bd”,
  • pospolicie brzmiąca „getIndex”,
  • pospolicie brzmiąca „addslashes”,
  • i pozornie pospolicie brzmiąca „_ut8_decode” – pozornie, bo ten underscore na początku jest nietypowy.

Wykorzystując ów nietypowy underscore możemy poszukać w Google, czy to nie jest jakaś znana funkcja. Jak się okazuje, istnieje tylko jeden skrypt, który zawiera tę funkcję oraz „addSlashes” i „getIndex” – to pochodzący z http://www.webtoolkit.info skrypt JS realizujący dekodowanie znaków „zakodowanych” algorytmem Base64.

No i faktycznie wydaje się, że to jest nasz skrypt, ale coś się nie zgadza. W oryginalnym skrypcie w jednym miejscu jest coś zupełnie inaczej. Zamiast tego dziwnego alfabetu wskazanego wcześniej jest zwyczajny alfabet o taki:

_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

Hmm, czyżby więc programiści z państwowej naszej instytucji jedynie podmienili alfabety?

Sprawdźmy! Fragment zakodowanego tekstu bez początkowego „enc” wrzucamy w zmienną „test”, podmieniamy alfabety i dekodujemy base64…

<?php
// fragment kodowanej wiadomości bez początkowego 'enc'
$test = '!331aa1bb!45!3!!49!32!50!381ab1a7!45y25!45yy91b9y23yy4y1y1a1y231a2!391a1y25y30!39!45y22yy3y20y29!36!33!401b8!38!471a0!52!38!491bb!45y25!45yy9171!35y29yy2!5!!39!49!32!49y26y29!40!53!35!34!36!44!391aby241a1!37!34yy21a3y25!49y28!44!38!49!32y27!381aby20!52!36!34y201a9!3!yy7!321bb!38!50!48y29!35!34yy21b8!39!50y27!5!!34yy3yy91b9y23yy4y1y1a1y231a2!391a1y25y30!40!39yy9!451a0!39yy9!47y28!44!38!49!32y29!35!34yy21b8!39!50y28y27!39!49yy61aa!38!49yy6y27!40!33y201bb!34yy3yy91bbyy9yy4y1y!52y251a1!39173y23yy4y1y1b9y23!46y231aay23!46!471aay26yy61b91b8!35y301a7!45y22yy3y20!3!!4!!34y1y!45y25!45y20y27yy9!451b9!45y30!49yy61a9!401abyy5!45y25!45y20y27!32!3!y20y23y29!3!y24!37y30!47yy5!43!3!1a4!52y22y30171!33yy2y27y29yy2y27y301a3y28y30!32yy5yy6!34y301a4!40yy2yy9yy51a8y29y22!46yy9!43y29!3!1a31b7y30!3!!48y22y30171!33yy2y27!3!!52yy2yy9yy51bay26!3!yy5!32y29y30!47!48y22y27y29yy2!34yy9yy6y24!37!33!3!y30yy6!43!3!172!34y271a4!3!!45y22yy3y20!34!381ab!52!48!401ab172!47!4!!50y281aa!381a1yy91a9yy9!471a4yy2!33!47172!34y29!3!!32yy4y291a3!48yy6yy9!451b9!45!3!yy71721aa!37!33yy61a3yy9!46!5!!45!391aa!521a8!36y23!33yy3!381aa!40!52!36!33y241b4!37y29yy91bbyy9!47!401ba!37!331a8!44yy9!46!5!!45!3!1aa!521a8!36y23!33yy3!381aa!40!52!36!33y23!45y22yy3y20y22!381aby28y27!381aby241a9!40yy71721aa!4!y29yy91a9yy9!46yy91aby22y30!3!1b9y23yy3yy91bbyy9';

$key = ["y1y", "yy2", "yy3", "yy4", "yy5", "yy6", "yy7", "yy8", "yy9", "y20", "y2y", "y22", "y23", "y24", "y25", "y26", "y27", "y28", "y29", "y30", "!3!", "!32", "!33", "!34", "!35", "!36", "!37", "!38", "!39", "!40", "!4!", "!42", "!43", "!44", "!45", "!46", "!47", "!48", "!49", "!50", "!5!", "!52", "!53", "1b4", "1bb", "1ba", "1b7", "1b8", "1b9", "1a0", "1a1", "1a2", "1a3", "1a4", "1ab", "1aa", "1a7", "1a8", "1a9", "170", "171", "172", "173", "174", "17b", "71a"];

$original = str_split("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");

$pairs = [];

for ($i = 0; $i < 65; $i++) {
    $pairs[$key[$i]] = $original[$i];
}

echo base64_decode(strtr($test, $pairs));

…sprawdźcie sami, że wynik wygląda tak:

[{"Regon":"000237297","RegonLink":"<a href='javascript:danePobierzPelnyRaport(\"000237297\",\"DaneRaportPrawnaPubl\", 0);'>000237297<\/a>","Typ":"P","Nazwa":"PUBLICZNA SZKOŁA PODSTAWOWA NR.2 IM.MIKOŁAJA KOPERNIKA W SZYDŁOWCU","Wojewodztwo":"MAZOWIECKIE","Powiat":"szydłowiecki","Gmina":"Szydłowiec","KodPocztowy":"26-500",

Czyli sukces! 🙂

Przy okazji wyjaśnia się nazwa jednej z funkcji w skrypcie: „bd” to po prostu „base64_decode”.

Na koniec kilka pytań: po co właściwie te dane są kodowane? Przecież owa instytucja udostępnia informację publiczną. Jaki jest sens utrudniania korzystania z API? Tu nie ma żadnych tajemnic przecież. Mogą pojawić się dane osobowe, ale zwyczajnie podlegają pod RODO jeżeli ktoś chciałby na nich zbijać pieniądze.

Nie wiem po co takie dziwne utrudnienia. Dodatkowo, dane zwracane powyższym kodowaniem są objętościowo większe. Nie tylko dlatego, że base64 standardowo zwiększa objętość, ale i dlatego, że użyto alfabet o „literach” złożonych z wielu znaków.

Prosta metoda blokowania SPAMu z formularza kontaktowego

W jednym z projektów, w których brałem udział, jeden z formularzy kontaktowych był źródłem licznego SPAM-u pochodzącego od internetowych botów. Z różnych przyczyn nie chcieliśmy instalować żadnych dodatkowych modułów czy wtyczek ani też nie chcieliśmy komplikować formularza stosując CAPTCHA czy coś podobnego. Postanowiliśmy wypróbować pewne proste rozwiązanie. Po wielu miesiącach stosowania mogę powiedzieć, że nasza prosta metoda się bardzo dobrze sprawdziła.

W formularzu dodałem dwa pola typu „hidden” o nazwach „fullname” oraz „password”. Fullname jest polem pustym i niewidocznym – żywy użytkownik nigdy nie wprowadzi tu żadnej wartości. Wiele botów wpisze tutaj jednak wygenerowane imię i nazwisko. Na tej podstawie już można wyciąć trochę ruchu. Prosta pułapka.

Pole „password” ma jednak wartość: to zakodowany timestamp. Zakodowany odwracalnie, bo w kontrolerze jego wartość jest odzyskiwana i porównywana z czasem na serwerze. Jeżeli różnica jest większa niż pewien ustalony czas, system zakłada, ze wiadomość pochodzi od człowieka, bo ten – w odróżnieniu od komputerowego bota – potrzebuje czasu, aby napisać wiadomość.

Innymi słowy, cały ów antyspamowy filtr składa się z:

  • dwóch ukrytych pól input,
  • jednego większego IFa w kontrolerze.

Co zaskakujące, ten banalny system zdaje się działać niemal w stu procentach. Sytuacje, w których coś zostało przepuszczone (albo niesłusznie zatrzymane) są jednostkowe.

Dostęp do wyszukanych osób w planie bezpłatnym MyHeritage

MyHeritage, zgodnie z prawem, nie chroni danych osób zmarłych. Natomiast w wynikach wyszukiwania („zbadaj osobę”) po kliknięciu na link do profilu osoby zmarłej wyświetlony zostanie monit o zakup płatnego abonamentu i nie ma sposobu, aby go ominąć – brak jakiegoś przycisku „Pomiń”, „Zamknij” czy „Przejdź do osoby”. Taki sposób MyHeritage ma na zdobywanie części klientów. Kto jednak używał MyHeritage przez dłuższy czas, ten wie, że do tych profili istnieje link dostępowy, bo różnymi drogami można do tych osób dotrzeć i czasami sam serwis go podpowiada. Taki link można również wytworzyć bazując na wynikach wyszukiwania. Poprawnie skonstruowany będzie miał on postać taką:

https://www.myheritage.pl/person-X_Y_Z/

Gdzie X to numer osoby, a Y i Z to numer witryny oraz drzewa (zazwyczaj często ten sam, nie zajmowałem się ustaleniem który jest który).

Tymczasem w wynikach wyszukiwania są linki typu:

https://www.myheritage.pl/FP/search-plans.php?s=103900133&colId=1&itemId=385852852-1-500030&indId=individual-103900133-7500002&rfr=tree

W powyższym linku interesujące nas dane są zawarte w „itemID”, czyli „385852852-1-500030”. Pierwsza liczba to jest nasze Y i/lub Z. Druga i trzecia liczba razem złączone dają X. Czyli działający link do osoby będzie taki:

https://www.myheritage.pl/person-1500030_385852852_385852852/

Zmienianie linków można sobie zautomatyzować do tzw. bookmarkletu, czy do postaci zakładki na pasku przeglądarki, której naciśnięcie przepisze wszystkie widoczne linki „search-plans” do „person”. Przykładowo, w przeglądarce Chrome należy z menu wybrać „Zakładki” i później „Menedżer zakładek”. W nowym widoku należy z menu wybrać „Dodaj zakładkę”. Można jej nadać jakąś nazwę, np. „Przepisz linki MyHeritage” i następnie w polu URL zamiast adresu WWW należy wprowadzić poniższy kod JavaScript (jest to jedna linia tekstu):

javascript:(function() { $('.record_link.recordTitle').each(function (i) { var result = /itemId=(\d+)-(\d+)-(\d+)/.exec(this.href); if (result) this.href = 'https://www.myheritage.pl/person-' + result[2] + result[3] + '_' + result[1] + '_' + result[1] +'/'; }) })();

Od tej pory kliknięcie w zakładkę w widoku wyszukiwania przepisze linki na prowadzące do osoby.

Powyższe to tylko przykład przepisujący linki do osób z drzew genealogicznych. MyHeritage wyświetla wyniki też i z innych źródeł i tam przepisywanie linku musiałoby działać inaczej.

Czasopisma policyjne w głębokiej sieci

Głęboka sieć to część Internetu, która nie jest indeksowana przez wyszukiwarki internetowe i tym samym pozostaje poza zasięgiem typowego Internauty. Niektóre czasopisma policyjne są elementem głębokiej sieci z przyczyn technologicznych – z jednej strony są one publicznie dostępne dla każdego poprzez oficjalną stronę Policji http://www.gazeta.policja.pl/ , ale z drugiej strony zakodowano je w formacie PDF z istotnymi utrudnieniami dla wyszukiwarek:

  • Te PDFy, które zawierają w sobie przeszukiwalny tekst, stosują bardzo dziwne kodowania znaków i rozbicia lub połączenia wyrazów, które są niewidoczne dla człowieka, ale skutecznie utrudniają pracę robotom wyszukiwarek;
  • Wiele PDFów zawiera po prostu skany starych czasopism a wyszukiwarki obecnie nie radzą sobie dobrze z taki treściami graficznymi (chociaż kiedyś sobie poradzą);

W związku z tym, chcąc przeszukiwać treść takich czasopism Internauta ma poważny problem – musi przeglądać wszystkie ręcznie. Do przeglądu ma 800+ numerów od 12 do 50 stron każde wydanie. Chodzi tutaj o czasopisma:

  • Policja 997,
  • Policja 997 wydanie specjalne,
  • Gazeta Policyjna,
  • Magazyn Kryminalny,
  • Patrol,
  • Wiadomości Sekcji Polskiej IPA,
  • Policja Łódzkie,
  • Przegląd Prewencyjny,
  • Stołeczny Magazyn Policyjny,
  • Kwartalnik Prawno-Kryminalistyczny,
  • Kwartalnik policyjny.

Częściowo można sobie z tym problemem poradzić i zbudować lokalną wyszukiwarkę lub wykorzystać jakiś dostępny mechanizm wyszukujący. Najpierw jednak trzeba wszystkie PDFy pobrać a następnie przetworzyć ich zawartość programem do optycznego rozpoznawania znaków (OCR) na poprawną tekstowo postać. Aby wspomóc pobieranie PDF-ów przygotowałem odpowiedni skrypt i zamieściłem w serwisie GitHub:

https://github.com/gakowalski/czasopisma-policyjne

Do pobrania skryptem jest 9+ GB danych.

Do OCR polecam NAPS2, które to oprogramowanie jest darmowe, obsługuje język polski i z tego, co sobie testowo uruchamiałem, to względnie radzi sobie z tymi PDFami. Do przetworzenia jest sporo, więc radzę uzbroić się w cierpliwość.

Wynik przetworzenia polecam zawrzeć również w pliki PDF, aby móc skorzystać z „Wyszukiwania zaawansowanego” w darmowym oprogramowaniu Adobe Reader.

Dlaczego nie przejmuję się wirusami komputerowymi

Wiele lat temu porzuciłem stosowanie programów antywirusowych i przejmowanie się wirusami. Było to jeszcze zanim nastała era systemów komputerowych z domyślnym podstawowym antywirusem takich jak współczesne Windowsy. Dlaczego od tego odszedłem? Powody były dwa:

  1. Zrozumiałem dobrze którędy wirusy mogą dostać się do mojego komputera i przyjąłem takie reguły pracy, aby nigdy nie stworzyć możliwości zarażenia.
  2. Zaobserwowałem, że programy antywirusowe są bardzo obciążające dla pracy komputera i bardzo często przeszkadzają w sprawnym działaniu systemu.

Warto zauważyć, że w pewnym momencie niektóre antywirusy same stały się „wirusowe” – obciążały komputer znacząco a instalowały się niemalże potajemnie (np. McAffee dołączany cichcem do Flasha). Pojawiły się też w pewnym momencie programy szpiegujące, które udawały narzędzia do usuwania tzw. malware i adware, czyli „złośliwego oprogramowania”.

Wszystkiemu temu postanowiłem powiedzieć: nie.

Jakie są podstawowe zasady, które przyjąłem, aby chronić się przed wirusami? Oto one:

  1. W systemie operacyjnym należy wyłączyć tzw. autoodtwarzanie, czyli automatyczne uruchamianie programów z dysków CD, USB, kart pamięci i innych.
  2. Nie używać nielegalnego oprogramowania albo oprogramowania z podejrzanego źródła. Kiedyś nielegalne oprogramowanie było dosyć powszechne, bo jakoś mentalnie my w Polsce nie mogliśmy się szybko przestawić na legalność. Dzisiaj w zasadzie do każdego zadania można znaleźć legalny, darmowy software i to jeszcze open-source. Ważne jest jednak to, aby pobierać taki software z sensownego źródła, czyli np. strony internetowej autora czy producenta a nie z jakieś dziwacznej domeny „pobieram24h-programooosy.pl”. Swoją drogą, gro wirusów dawniej przenosiło się w crackach do gier. Dzisiaj szczęśliwie świat się zmienił i ludzie nie chcą nawet legalnej gry, jeżeli nie jest podłączona do platformy typu Steam czy podobnej. Legalne i płatne oprogramowanie znalazło sposób na bycie atrakcyjniejszym niż nielegalne.
  3. Należy utrzymywać aktualne wersje oprogramowania. Nie tylko przeglądarek internetowych, ale też każdego, które ma związek z danymi pochodzącymi z sieci. Czyli: czytnik PDF-ów, arkusz kalkulacyjny, edytor tekstu.
  4. Należy mieć włączone wyświetlanie na rozszerzeń plików w systemie Windows. Jest to ważne, bo jeżeli szukamy dokumentu PDF albo Word a dostajemy plik z rozszerzeniem EXE, BAT, COM czy CMD, to od razu powinno to wzbudzić niepokój – rzekłbym nawet, że zwykły użytkownik powinien taki plik usunąć natychmiast. Znajomość rozszerzeń plików to istotna wiedza, warto ją nabyć i nie polegać na uproszczeniach, które w tym zakresie oferują niektóre systemy operacyjne i aplikacje.
  5. Należy pilnować się w Internecie. W szczególności dotyczy to chyba poczty elektronicznej i jej rozmaitych załączników. Po pierwsze, musimy widzieć rozszerzenia załączników i je oceniać tak jak przy zwykłych plikach. Po drugie, musimy ocenić źródło maila i samego maila. Czy źródło jest znane, podejrzane? Czy mail jest jakiś niespodziewany, niezamówiony, sensacyjny, nawołujący do podjęcia jakieś akcji typu „kliknij w link”, „otwórz załącznik”? Jeżeli tak, to należy mieć się na baczności.

To powyżej to są podstawowe zasady. Oprócz nich mam kilka bardziej technicznych trików polegających na wyłączaniu lub blokowaniu pewnych zaawansowanych możliwości systemu operacyjnego, aby utrudnić działanie takiego wirusowi-spryciarzowi, który by się jednak przedostał. Wydaje mi się jednak, że powyższe pięć zasad na czasy współczesne zupełnie wystarcza.

Kiedy być może warto mieć antywirusa? Gdy współdzielisz komputer z użytkownikami, którym nie można zaufać, którzy nie stosują się do wskazanych reguł bezpieczeństwa. Zamiast antywirusa można próbować ograniczyć uprawnienia tych osób, ale nie wydaje mi się, aby to było wystarczalne.

Moje narzędzia pracy w 2019 roku

W ślad za podobnym postem z 2017 roku chciałbym przedstawić co najczęściej pojawia się w mojej codziennej pracy.

Systemy operacyjne

Najczęściej Windows 10 oraz Windows 7 do prac w środowisku graficznym. Do prac innego rodzaju – a w szczególności prac serwerowych – Linuxy. Najczęściej CentOS 6/7, rzadziej Ubuntu i jego warianty.

Oprogramowanie

  • Za menedżer plików w systemie Windows służy mi darmowy Double Commander. W Linuxach nie korzystam z żadnego specjalnego menedżera. Jeżeli czegoś nie chce mi się wypisywać z linii poleceń to stosuję prosty webowy menedżer zawarty w Webmin.
  • Klient bazy danych dla Windows to HeidiSQL. Z poziomu Linuxa po prostu polecenie mysql. Gdy się nie da inaczej, używam webowego phpMyAdmin lub Adminer. Ostatnie lata skierowały mnie w zasadzie głównie do pracy z MySQL i MariaDB. Gdzieś się zapodziały Oracle i PostgreSQL.
  • Do przesyłu plików tylko WinSCP.
  • Do pracy przez SSH tylko PuTTY z dodatkiem Pageant jako że preferuje łączenie z użyciem kluczy SSH nad loginy i hasła. Takie połączenie jest wspierane przez HeidiSQL i WinSCP. Poza tym, często korzystam z tunelowania SSH i wymienione narzędzia dobrze je wspierają.
  • Do wersjonowania kodu: tylko git i do wygodnej pracy desktopowej GitHub for Desktop. Naturalnie na Linuxach git z linii poleceń. Wykupione płatne konto w GitHub.
  • Edytory kodu: w środowisku desktopowym najczęściej Atom a gdy się nie da to Notepad++. W najgorszym wypadku może być cokolwiek, np. Notatnik. Nie przeszkadza mi brak kolorowania składni czy innych bajerów. W systemach Linux przekonałem się natomiast do Vim.
  • Przeglądarki internetowe bardzo standardowe: Chrome, Firefox, Edge.
  • Do prac graficznych: IrfanView oraz Paint.Net.
  • Do różnych diagramów wykorzystuję yEd.
  • Menedżer haseł: KeePass 2.
  • Do prac z webservice’ami: SoapUI. Nowe wersje trochę działają chyba inaczej (gorzej?) niż starsze, ale SoapUI używam i tak wtedy, gdy naprawdę już nie chce mi się napisać kodu albo muszę coś bardzo szybko sprawdzić.
  • Obsługa kontenerów – docker z linii poleceń, ale częściowo webowa obsługa z użyciem Portainer . Szczególnie użyteczne przy rożnego rodzaju dziedziczonym kodzie, ale nie tylko. Kontenery dużo porządkują.

Frameworki i języki programowania

  • Ostatnie lata to głównie PHP z okazjonalnym pojawianiem się jakiś odmian Javy, Pythona i innych takich. Tym nie mniej przyszłość rysuje się bardzo PHP-owo.
  • Stawiam Laravel ponad Symfony.
  • Arkusze stylów: SASS.
  • VanillaJS ponad jQuery i inne takie, chociaż nie zawsze się da, bo nie działając w zespole nie każdy ma chęć pisać w czystym JS.

Inne

  • Rejestracja domen: od lat w gnum.pl. Ceny mają najlepsze, ale trzeba się pilnować, bo czasami wyślą powiadomienie o wygasaniu a czasami nie.
  • Certyfikaty SSL – Let’s Encrypt wszędzie, gdzie to możliwe.

Sprawne określanie użycia dysku w określonym folderze systemie Linux

Podstawowym narzędziem do oceny użycia dysku jest du, które można dodatkowo okiełznać użytecznym aliasem, aby wyniki od razu sortować np.:

alias folder-size='du --all --human-readable --max-depth=1 --block-size=1M | sort --human-numeric-sort'

Albo wersja o wyższych uprawnieniach:

alias folder-size-sudo='sudo du --all --human-readable --max-depth=1 --block-size=1M | sort --human-numeric-sort'

Powyższe rozwiązania wciąż mają istotną wadę: nie wykrywają poprawnie plików ukrytych (.) i w związku z tym próbując dociec co zajmuje miejsce na serwerze możemy namierzyć folder, ale możemy nie móc namierzyć konkretnego pliku.

Jedynym sensownym rozwiązaniem powyższego jest tak naprawdę użycie narzędzia ncdu, które w sposób interaktywny (z użyciem ncurses) pozwala badać dany folder.

W przypadku CentOS instalacja jest banalna: sudo yum install ncdu. W przypadku innych Linuxów zapewne będzie analogicznie.

Wklejenie tekstu przez symulowane wpisywanie

Niektóre interfejsy blokują możliwość wklejenia tekstu poprzez standardowe CTRL+V lub wybranie pozycji „Wklej” z menu a wymuszają wpisywanie tekstu ręcznie. Taki przypadek miałem ostatnio korzystając z Platformy Usług Elektronicznych ZUS, która obsługę formularzy realizuje przez już trochę przestarzałą technologię Flash.

Aby sobie dać radę z takim czymś należy zainstalować sobie aplikację AutoHotkey a następnie utworzyć sobie gdzieś skrypt podpinający pod CTRL+SHIFT+V wklejanie przez symulowanie użycia klawiatury i go uruchomić. Od teraz wskazany skrót klawiszowy wkleja tekst symulując naciśnięcie serii klawiszy.