6.3. Parser

6.3.1. Wstęp

Moduł parser jest oparty na skryptowym języku T-Script, którego głównym zadaniem jest generowanie plików tekstowych. Może być używany do przetwarzania szablonów z danymi pobieranymi z różnych źródeł np. baz SQL lub plików tekstowych. W naszym przypadku treść skryptu (szablon) jest przechowywany w bazie danych, dlatego istnieje możliwość jego edycji poprzez LMS-UI. W przyszłości moduł parser może zastąpić większość modułów demona.

Przed kompilacją modułu upewnij się, że posiadasz w systemie pakiety bison (co najmniej w wersji 1.875) oraz flex.

6.3.2. Konfiguracja

Parser posiada następujące opcje:

6.3.3. Składnia

Składnia języka T-Script jest podobna do składni innych popularnych języków takich jak C czy JavaScript, ale dokonano pewnych zmian mających na celu ułatwienie tworzenia szablonów. Wszystkie podane polecenia powinny być zapisywane wewnątrz klamer { }. Dane poza klamrami zostaną zapisane do pliku wyjściowego (lub jeśli go nie zdefiniowano, pominięte). Wielkość liter ma znaczenie.

Wyrażenia:

Komentarze:

Podstawowe polecenia:

Podstawowe funkcje:

6.3.4. Rozszerzenia

Rozszerzenia to dodatki do biblioteki tscript. Są to funkcje i stałe, które można używać w skryptach. Poniżej przedstawiono rozszerzenia udostępnione w lmsd.

Notatka

Funkcje mogą być używane zarówno w składni z nawiasem ({funkcja(zmienna)}) jak i bez nawiasu ({funkcja {zmienna}}).

6.3.4.1. Exec

Wykonywanie poleceń powłoki umożliwia funkcja exec(). Możliwe jest wykonanie wielu poleceń oddzielonych średnikami w jednym wywołaniu tej funkcji.

  • Wykonywanie poleceń powłoki.

    {exec <polecenie>}

6.3.4.2. String

'String' zawiera podstawowe funkcje do operowania na ciągach znaków.

  • Usunięcie "białych" znaków z początku i końca ciągu znaków.

    {trim <ciąg_znaków>}

6.3.4.3. SQL

Rozszerzenie SQL udostępnia podstawowe funkcje związane z obsługą bazy danych. Pozwala na wykonywanie poleceń SQL.

  • Polecenia SQL

    {SELECT <dalszy_ciąg_zapytania>}
    {INSERT <dalszy_ciąg_zapytania>}
    {DELETE <dalszy_ciąg_zapytania>}
    {UPDATE <dalszy_ciąg_zapytania>}
    {CREATE <dalszy_ciąg_zapytania>}
    {DROP <dalszy_ciąg_zapytania>}

  • Liczba wierszy, których dotyczy zapytanie.

    {rows(<zapytanie_sql>)}

  • Zabezpieczenie znaków specjalnych w celu użycia w zapytaniu SQL. W szczególności chodzi o apostrofy i backslashe. Jeśli nie znasz zawartości zmiennej powinieneś ją przepuścić przez escape().

    {escape(<zmienna>)}

6.3.4.4. Consts

Rozszerzenie ściśle związane z LMS-em. Umożliwia tworzenie skryptów bez znajomości struktury bazy danych. Zawiera predefiniowane stałe, które zawierają dane z bazy. Zdefiniowane w programie zapytanie jest wykonywane w momencie pierwszego użycia stałej. Nazwy stałych należy pisać dużymi literami. Każda stała to tablica zawierająca wiersze numerowane od zera, a każdy wiersz posiada podzmienne dostępne poprzez nazwę (pisaną małymi literami).

  • CUSTOMERS - lista klientów:

    id - ID klienta
    lastname - nazwa/nazwisko klienta
    name - imię klienta
    status - status
    address - adres klienta
    zip - kod pocztowy
    city - miasto
    email - adres e-mail
    phone1, phone2, phone3 - telefony
    ten - NIP
    ssn - PESEL
    info - informacje o kliencie
    message - treść ostrzeżenia
    warning - status ostrzeżenia (suma statusów wszystkich komputerów klienta)
    access - status dostępności (suma statusów wszystkich komputerów klienta)
    balance - bilans klienta

  • NODES - lista komputerów (i adresów urządzeń sieciowych):

    id - ID komputera
    owner - nazwa/nazwisko i imię klienta
    ownerid - ID klienta ('0' w przypadku urządzeń)
    name - nazwa komputera (adresu urządzenia)
    access - status: włączony/wyłączony (1/0)
    warning - status ostrzeżeń: włączone/wyłączone (1/0)
    netdev - ID urządzenia, do którego jest podłączony
    lastonline - czas ostatniej aktywności
    info - dodatkowe informacje
    message - treść ostrzeżenia
    mac - adres MAC
    passwd - hasło
    ip - adres IP
    ip_pub - publiczny adres IP
    linktype - typ połączenia (0-kabel, 1-radio)

  • NETWORKS - lista sieci:

    id - ID sieci
    name - nazwa sieci
    address - adres IP
    mask - maska (xxx.xxx.xxx.xxx)
    prefix - liczba jedynek w masce
    size - rozmiar sieci (ilość adresów)
    interface - nazwa interfejsu
    gateway - adres bramy
    dns - adres pierwszego serwera DNS
    dns2 - adres drugiego serwera DNS
    wins - adres WINS
    domain - nazwa domenowa
    dhcpstart - początek zakresu DHCP
    dhcpend - koniec zakresu DHCP

6.3.4.5. Net

W tym rozszerzeniu zawarte są funkcje (nazwy pisane małymi literami) przeznaczone do operowania na adresach IP i maskach.

  • Zamiana maski sieciowej w formacie xxx.xxx.xxx.xxx na liczbę (bitów).

    mask2prefix(<maska>)

  • Zamiana adresu IP w formacie 4-oktetowym na liczbę.

    ip2long(<adres>)

  • Zamiana adresu IP podanego jako liczba na format xxx.xxx.xxx.xxx.

    long2ip(<adres>)

  • Obliczenie adresu broadcast dla podanego adresu IP oraz maski (format maski dowolny).

    broadcast(<adres/maska>)

6.3.5. Przykładowe skrypty

Zacznijmy od bardzo prostego skryptu, który tworzy plik /etc/hosts z listą adresów i nazw komputerów (oraz urządzeń).

Przykład 6-1. Parser: Tworzenie pliku /etc/hosts

{result = SELECT name, inet_ntoa(ipaddr) AS ip FROM nodes}\
127.0.0.1    localhost
{for (r=0; r<number(result); r++)}\
{result[r].name}\t{result[r].ip}
{/for}\

Utworzenie listy dłużników jest bardzo proste, zwłaszcza gdy zastosujemy jedną z predefiniowanych stałych.

Przykład 6-2. Parser: Lista dłużników

{for (r=0; r<number(CUSTOMERS); r++)}\
    {if (CUSTOMERS[r].balance < 0)}\
{CUSTOMERS[r].lastname} {CUSTOMERS[r].name}\t{CUSTOMERS[r].balance}
    {/if}
{/for}\

Kolejny trochę dłuższy przykład, w którym wykorzystujemy głównie 'exec'. Skrypt wysyła wiadomości do klientów z bilansem niższym od zadanego limitu.

Przykład 6-3. Parser: Zamiennik modułu notify

{limit = 0}
{month = exec date +%B}
{year = exec date +%Y}
{customers = SELECT customers.id AS id, email, pin, name, lastname,
        SUM((type * -2 +7) * cash.value) AS balance
        FROM customers
        LEFT JOIN cash ON customers.id = cash.customerid AND (cash.type = 3 OR cash.type = 4)
        WHERE deleted = 0 AND email!=''
        GROUP BY customers.id, name, lastname, email, pin
        HAVING SUM((type * -2 +7) * cash.value) < {limit}}

{for(i=0; i<number(customers); i++)}

    {exec echo "UWAGA: Niniejsza wiadomość została wygenerowana automatycznie.

Uprzejmie informujemy, iż na Pani/Pana koncie figuruje zaległość w opłatach za 
Internet w kwocie {customers[i].balance*-1} zł.

Jeżeli należność za bieżący miesiąc, to jest {trim(month)} {trim(year)}, została już
uregulowana prosimy zignorować tę wiadomość.

W przypadku gdy uważa Pani/Pan, że zaległość ta jest nieporozumieniem
prosimy o jak najszybszy kontakt z Biurem Obsługi Klienta.

Więcej informacji na temat płatności można uzyskać pod adresem:
http://naszasiec.pl/mojekonto/

W celu uregulowania należności prosimy o kontakt:

Nasz Siec ASK - Biuro Obsługi Klienta
Gwidon Mniejważny
telefon: 0-606031337
e-mail: gwidonm@naszasiec.pl

PS. Poniżej załączamy ostatnie 10 operacji na Państwa koncie.
--------------+--------------+-----------------------------
     Data     |    Kwota     |           Komentarz
--------------+--------------+-----------------------------" > /tmp/mail}

    {last10 = SELECT comment, time, CASE WHEN type=4 THEN value*-1 ELSE value END AS value
            FROM cash WHERE customerid = {customers[i].id}
            ORDER BY time DESC LIMIT 10}
    
    {for(j=0; j<number(last10); j++)}
    
        {exec echo "{last10[j].time}|\t{last10[j].value}|\t{last10[j].comment}" >> /tmp/mail}
    
    {/for}

    {exec mail -s "Powiadomienie o zaleglosciach" -r lms@domain.tld {customers[i].email} < /tmp/mail}

{/for}