Conditional Formatting και Φιλτράρισμα τιμών σε Speadsheets στο LibreOffice Calc

Στην εργασία μου μερικές φορές για να δείξουμε πως θα παίζει ένας αλγόριθμος αξιοποιούμε το google docs spreasdheets. Ένα ωραίο feature αυτού είναι το conditional formatting, δηλαδή ένας τρόπος να ορίζω ανάγωγα με την τιμή του κελιού, το background χρώμα του αυτού. Έτσι σαν υπέρμαχος του ελεύθερου λογισμικού, ήθελα να δω πως είναι εφικτό σε libreoffice που διανέμονται με GNU/Linux από την ημέρα που το εγκαθιστάς στο pc σου και πλέον παίρνει μια ανάσα (Shameless ad).

Έτσι σαν σενάριο χρήσης έχουμε το εξής, κρατάμε μια λίστα με anime που έχουμε δει σε ένα spreasheet (Ι know, I know, ξέρω ότι υπάρχει και το myanimelist αλλά τώρα κάνουμε ένα demonstration του feature στο libre office). ‘Εχουμε 2 στήλες: την στήλη Α που έχει τον τίτλο και την στήλη Β που κρατάμε την τιμή ΝΑΙ η ΟΧΙ αναλόγως εάν το έχουμε δει η όχι. Το φύλλο μας είναι αυτό που δείχνει η κάτωθι εικόνα:
Το λογιστικό μας φύλο προ επεξεργασίας

Όπως βλέπετε η πρώτη γραμμή έχει μια μορφοποίηση την οποία δεν θέλουμε να την πειράξουμε. Η στήλη η οποία θέλουμε να πειράξουμε είναι Β η οποία καταγράφει εάν έχουμε δει το ανιμέ που είναι στην ίδια γραμμή ή όχι στην στήλη A. Η τιμή η οποία υποδεικνύει ότι το έχουμε δει είναι η λέξη YES και το κελί της τιμής αυτής θα έχει πράσινο χρώμα ενώ η τιμή που υποδεικνύει ότι δεν το έχουμε δει είναι η λέξη NO και θα έχει κόκκινο χρώμα.

Για να πετύχουμε το formatting που έχουμε ακολουθούμε τα παρακάτω βήματα:

  1. Επιλέγουμε Μορφή->Μορφοποίηση Υπό όρους -> Συνθήκη:
    Μενού επιλογής conditina formatting
  2. Στο παράθυρο που μας άνοιξε επιλέγουμε ορίζουμε σαν περιοχή B:B;B1 όπως βλέπετε στην παρακάτω εικόνα:Επιλογή Κελιών Προς ΜορφοποίησηΜε την επιλογή αυτή ουσιαστικά λέμε επέλεξε την στήλη Β πλην του κελιού Β1.
  3. Εφόσον επιλέξαμε το εύρος θέλουμε να ορίσουμε την μορφοποίηση για το κελί όταν η τιμή είναι YES. Στη δική μας περίπτωση θέλουμε ένα πράσινο Background. Έτσι για να το κάνουμε αυτό στον Όρος 1 ορίζουμε όπως είναι η εικόνα:

    Όπως βλέπετε ορίσαμε την τιμή του κελιού ίση με «YES» τα « αξιοποιούνται όταν έχουμε λεκτικής μορφής τιμες. Ακόμη αξιοποιήσαμε την τεχνοτροπία good που είναι μια προεπιλεγμένη που μας δίνει έτοιμη το libreoffice. Ακόμη μην σας παραξενεύει ότι έχει
    «ΝΟ» στο πεδίο Εφαρμογή τεχνοτροπίας είναι απλά απλά μια ενδεικτική τιμή για το πως θα εμφανίζετε.
  4. Ομοίως επιλέγουμε την default τεχνοτροπία bad και για την τιμή ΝΟ:
  5. Και μετά επιλέγουμε το κουμπί «Εντάξει»

Το αποτέλεσμα είναι το ακόλουθο:

Όπως βλέπετε υπάρχει οπτικός διαχωρισμός μεταξύ όσον anime έχω δει και δεν έχω δει.

Πλέον όμως πέρα από το να βλέπω με μια ματιά ποια anime έχω δει και ποιά όχι θέλω να μπορώ να τα φιλτράρω έτσι στις διακοπές μου να μπορώ να βλέπω ποια έχω δει έτσι να κανονίσω να τα δω. Για να δημιουργήσουμε ένα φίλτρο επιλέγουμε μια στήλη και κάνουμε κλικ στο κουμπί που είναι στο πάνελ των εικονιδίων όπως βλέπετε στην παρακάτω εικόνα:

Μετά στο παράθυρο που μας ανοίγει επιλέγουμε «Ναι»:

Πλέον στη στήλη θα εμφανίζετε ένα κουμπί με βελάκι κάνοντας κλικ σε αυτό θα μπορείτε να δείτε τις διακριτές τιμές:

Για την δική μας περίπτωση θέλουμε να φιλτράρουμε τις τιμές NO έτσι θα πρέπει να ακολουθήσουμε τα παρακάτω βήματα:

  1. Αποεπιλέγουμε το checkbox που είναι εκεί που λέει Όλα:
  2. Αναζητάμε την τιμή NO:
  3. Ελέγχουμε να είναι επιλεγμένη η τιμή NO και μετά Εντάξει. Εάν δεν είναι την επιλέγουμε εμείς.

Έτσι θα μας εμφανιστούν μόνο οι παρακάτω εγγραφές:

Αυτό βολεύει σε πάρα πολλές επιλογές όπως το να φιλτράρεις επιστημονικά ή στατιστικά δεδομένα ή ακόμα και σε business επίπεδο να κρατάς σε λογιστικό φύλλο σειρά διεργασιών και να αναζητάς ποιες έχουν γίνει.

Advertisements

Εμφάνιση και αλλαγή μηνύματος πριν το login σε Alpine Linux

Σε μια εργασία στο Παν/μιο Πειραιώς για το master μου έπρεπε να ετοιμάσω ένα virtual machine με μια ευπαθή εφαρμογή. Όμως δεν ήθελα να ήταν 1.000.0000 GB το καθένα έτσι επέλεξα μια μικρή και ελαφριά διανομή εν ονόματι Alpine Linux.

Όμως ήθελα να εμφανίζω πριν κάνει login ο χρήστης για ευκολότερο στήσιμο ένα μήνυμα που να λέει ip και κάποιες οδηγίες χρήσης για να τις κάνει στον supervisor (τίποτα σπουδαίο ip ή ένα hostname να βάλει στο hosts αρχείο)

Αυτό γίνετε αλλάζοντας το αρχείο /etc/issue και βάζοντας το κατάλληλο μήνυμα.
Στην περίπτωση μου ήθελα μια λίστα με όλες τις διευθύνσεις ip. Και το έκανα με το ακόλουθο script:


#!/bin/sh
echo "You can use one of the following ip addresses in order to look the page or even ssh into the machine" > /etc/issue
ip -4 -o addr show up  scope global | awk '{print $2,":",$4}'| sed -e "s/\/[1-9]*//" >> /etc/issue

Όμως έπρεπε να το τρέχω κατά το boot της διανομής. Ως εκ τούτου έκανα τα εξής βήματα:

1. Έτρεξα κατά rc-update add local default για να ενεργοποιήσω τα boot scripts όπως μου απάντησα πολύ αργότερα σε αυτό το site του stackexchange (πολύ καλό για hardcore linuxάδες ή επαγγελματίες που κάνου «κάτι παραπάνω» στο GNU/Linux).
2. Όρισα το script μου να είναι στο αρχείο /etc/local.d/UpdateIssue.start σαν root
3. Μετά το έκανα εκτελέσιμο με την εντολή chmod +x /etc/local.d/UpdateIssue.start

Και voila το αποτέλεσμα:

Results in Moot screen

Έτσι είσαι και ελαφρύς και δεν χρειάζεστε να κάνεις download τη μάνα και τον κύρη στις πρωχό εργασίες της σχολής 😉

Εγκατάσταση νεότερης έκδοσης minitube σε Ubuntu 18.04.

Λόγο ότι υπάρχουν αρκετά προβλήματα στο πακέτο που ο προγραμματιστής του minitube διανέμει από το site του. Αποφάσισα ότι πρέπει να το μεταγλωττίσω χειροκίνητα προκειμένου να παίζει όπως πρέπει. Τα προβλήματα που έχει είναι ότι:

  1. Δεν έχει ορίσει σωστά τις εξαρτήσεις κατά το κτίσιμο του πακέτου έτσι δεν πάει φρένο εάν δεν τις έχεις εγκατεστημένες.
  2. Ενώ παίζει με qt > 5.6 η μεταγλωττισμένη έκδοση θέλει 5.11 που δεν είναι στη 18.04LTS
  3. Χρειάζετε νεότερη έκδοση της βιβλιοθήκης libmpv από αυτήν των αποθετηρίων

Έτσι η διαδικασία έχει τα εξής χοντρικά βήματα:

  1. Εγκατάσταση της libmpv και εξαρτήσεων αυτής όπως και λογισμικού για κτίσιμο εφαρμογών.
  2. Δημιουργία API Key.
  3. Κτίσιμο και εγκατάσταση Minitube.

Εγκατάσταση της libmpv και εξαρτήσεων αυτής όπως και λογισμικού για κτίσιμο εφαρμογών.

Πρώτα εγκαθιστάμε κάποιες απαραίτητες εξαρτήσεις από τα αποθετήρια:

sudo apt-get install git dh-autoreconf build-essential libfreetype6-dev libfribidi-dev libfontconfig1-dev yasm libmp3lame-dev libx264-dev libfdk-aac-dev python libssl1.0-dev libpulse-dev python-pip

Μετά μέσω pip εγκαθιστούμε το youtube-dl:

sudo -H pip install -g youtube-dl

Μετά κατεβάζουμε το εργαλείο για την εγκατάσταση του libmpv από το αποθετήριο του git:

git clone https://github.com/mpv-player/mpv-build.git

Και το κτίζουμε με αυτό το κοκτέιλ των εντολών:

cd mpv-build
echo --enable-libx264 >> ffmpeg_options
echo --enable-libmp3lame >> ffmpeg_options
echo --enable-libfdk-aac >> ffmpeg_options
echo --enable-nonfree >> ffmpeg_options
echo --enable-libmpv-shared > mpv_options
./use-mpv-custom v0.29.1
./update
./rebuild -j4
sudo ./install
cd ..

Μετά επεκτείνουμε την μεταβλητή LD_LIBRARY_PATH με τις κατάλληλες τιμές ώστε να μπορεί το σύστημα να «βλέπει» την βιβλιοθήκη:

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

Και για ποιο μόνιμα αποτελέσματα μπορούμε είτε να το ορίσουμε σαν εντολή στο script στο ~/.profile εάν θέλουμε να έχει ισχύ μόνο για τον χρήστη μας:

echo "export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH" >> ~/.profile 

Ή για ποιο μόνιμα, για όλους τους χρήστες αποτελέσματα στο αρχείο /etc/environment

echo "LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH" | sudo tee -a /etc/environment

Δημιουργία API Key. (Μπορεί να γίνει παράλληλα με τα προηγούμενα βήματα όπως κτίζετε η εφαρμογή)

Το minitube τραβά από το youtube data api τα δεδομένα που χρειάζεστε και μέσω libmpv και youtube-dl τα αναπαράγει. Ως εκ τούτου χρειαζόμαστε ένα youtube data api key. Για να γίνει αυτό τα ακόλουθα βήματα χρειάζονται:

  1. Σύνδεση στο https://console.developers.google.com
  2. Μετά δημιουργούμε ένα νέο project όπως δείχνουν οι εικόνες:
    Explaining on how to create an youtube API key
    Form that created the project
  3. Μετέπειτα κάντε κλικ στο κουμπί «Enable Apis and Services».
    Enable APIS
  4. Στη φόρμα που μας εμφανίζετε αναζητούμε «Youtube Data API» και επιλέγουμε το «Youtube Data Api v3» όπως μας δείχνει η παρακάτω εικόνα:
    Selecting Youtube Data API
  5. Μετέπειτα κάνουμε κλικ στο κουμπί Enable με το μπλε χρώμα:
  6. Μετά πρέπει να δημιουργήσουμε τα Credentials κάνοντας κλικ στην πλαϊνή μπάρα που αναγράφει «Credentials» και έχει το κλειδάκι σαν εικονίδιο. (Δείτε παρακάτω εικόνα)
  7. Μετέπειτα στην οθόνη που εμφανίζετε κάνουμε κλικ στο «Create Credentials» και μετά κάνουμε κλικ στο «API Key»:
    Creating a youtube api Key
  8. Όταν έρθει η ώρα κάντε Copy Paste τη παρακάτω τιμή:
    API Key

Κτίσιμο και εγκατάσταση Minitube

Πλέον είμαστε έτοιμοι να βάλουμε την νεότερη έκδοση του minitube. Πρώτα εγκαθιστούμε τις περί QT εξαρτήσεις:

sudo apt install build-essential qt5-default qttools5-dev-tools qt5-qmake qtdeclarative5-dev libqt5sql5-sqlite libqt5x11extras5-dev

Μετά κάνουμε clone το αποθετήριο κώδικα του minitube και ορίζουμε την κατάλληλη έκδοση:

git clone --recursive https://github.com/flaviotordini/minitube.git
git checkout -b v3.0 tags/3.0

Και κτίζουμε όπου ^API_KEY^ το κλειδί που κάναμε στο προηγούμενο βήμα:

qmake "DEFINES += APP_GOOGLE_API_KEY=^API_KEY^"
make

Δοκιμάζουμε ότι όλα παίζουν σωστά με το να τρέξουμε:

./build/target/minitube

Και εγκαθιστούμε με την εντολή:

sudo make install

Διόρθωση προβλημάτων ήχου στις εμπρόσθιες θύρες ακουστικών Η/Υ με νέα μητρική σε παλιό κουτί Η/Υ

Όπως και εγώ, πιστεύω πως αρκετοί αντί να αγοράζετε ένα νέο desktop, απλά αναβαθμίζετε κομμάτι – κομμάτι τον Η/Υ σας διατηρώντας το παλιό κουτί, έτσι μετά από μερικά χρόνια αναβαθμίζετε και τη μητρική πλακέτα. Σε αυτήν την περίπτωση θα πρέπει να βεβαιώθητε υπό μια μορφή το hardware φέρνει τον ήχο στα ακουστικά του Η/Υ σας. Υπάρχουν 2 τρόποι στον οποίο γίνετε αυτό:

  • Δια του παλαιότερου AC’97, στον οποίον ο ήχος των ακουστικών μπορεί να μεταφερθεί και στα ηχεία παράλληλα.
  • Δια Ιntel HD στον οποίων δίνετε η δυνατότητα εντοπισμού πότε τα ακουστικά συνδέονται στον Η/Υ, λόγο ότι θεωρούνται διαφορετικές έξοδοι. Έτσι αυτόματα από το εκάστοτε λειτουργικό μπορεί να διακόπτει τον ήχο στα ηχεία του Η/Υ.

Εάν έχετε μια νεότερη μητρική κατά πάσα πιθανότητα ο εμπρόσθιος ήχος να είναι σε intel HD που σημαίνει ότι θα πρέπει «χεράτα» να ανεβάζετε την ένταση του ήχου για να ακούτε στα μπροστινά ακουστικά, δηλαδή να μην εντοπίζετε το ότι καρφώσατε το βύσμα των ακουστικών.

Σε αυτήν την περίπτωση δείτε εάν η μητρική σας υποστηρίζει ΚΑΙ το πρότυπο AC’97 στο εγχειρίδιο μετά μπορείτε στο UEFI menu (aka BIOS Menu) να ρυθμίσετε από IntelHD σε AC97.

Ακόμη μπορείτε να βεβαιωθείτε ότι ο μπροστινός ήχος είναι AC97 βλέποντας το βύσμα του καλωδίου που συνδέετε στην πλακέτα της υποδοχής των ακουστικών εάν έχει καλωδιάκια που ΔΕΝ πάνε προς τα μπρός αλλά συνδέουν κάποια πινάκια της κατάλληλης υποδοχής της μητρικής μεταξύ τους ή και το αναγράφει πάνω στο βύσμα.

Εναλλακτικά μπορείτε να παίξετε με τις ρυθμίσεις στο bios όσο αφορά τον ήχο και να δείτε τα αποτελέσματα. Σε περίπτωση Ubuntu GNU/Linux εάν επιλέξετε την επιλογή για την έξοδο των ακουστικών τότε θα ακούτε ήχο ΚΑΙ από τα μπροστινά ακουστικά ΑΛΛΑ και από τα ηχεία Η/Υ, παρόμοια συμπεριφορά θα υπάρχουν και σε άλλα λειτουργικά συστήματα και άλλες διανομές GNU/Linux.

Γράψτε Ιαπωνικά σε Ubuntu linux 18.04 μέσω anthy

Για την εγκατάσταση του anthy δίνουμε στο τερματικό τις παρακάτω εντολές:

<pre><code>
sudo apt-get install ibus-anthy anthy*
sudo apt-get install fonts-takao*
</code></pre>

Και μετά αποσυνδεθείτε (κάντε logout) και επανασυνδεθείτε (κάντε login). Ύστερα ανοίξτε το κεντρικό μενού (activities) είτε πατώντας το start (super) πλήκτρο είτε επιλέγοντας το εικονίδιο Το εικονίδιο για τις δραδτηριότητες (κεντρικό μενού εφαρμογών). Με το που το κάνετε αυτό θα δείτε το παρακάτω παράθυρο, σε αυτό αναζητήστε την λέξη settings ή την λέξη ρυθμίσεις και κάντε κλικ στο αντίστοιχο εικονίδιο:

Επιλογή των ρυθμίσεων από τις δραστηριότητες.

Ύστερα στο παράθυρο που έχει ανοίξει επιλέγουμε «Περιοχή και Γλώσσα» και ύστερα κάνουμε κλικ στο εικονίδιο με το σύμβολο + στο section «Πηγές εισόδου»:

Επιλογές για [ρποσθήκη γλώσσας στο πάνελ των ρυθμίσεων.

Στο παράθυρο που έχει ανοίξει πατάμε το εικονίδιο με τις 3 κάθετες βούλες () και αναζητάμε την λέξη «Ιαπωνικά» στο πλαίσιο εισόδου που εμφανίζετε. Μετέπειτα επιλέγουμε την επιλογή Ιαπωνικά:

Ύστερα στις επιλογές επιλέγουμε «Ιαπωνικά(Anthy)»:

Τέλος κάνουμε κλικ στο κουμπί «Προσθήκη».

Μετά επιλέγουμε την γλώσσα που προστέθηκε και με την χρήση του βέλους την μεταβιβάζουμε αμέσως μετά την Αγγλική επιλογή γλώσσας. Αυτό γίνετε λόγο ότι η μέθοδος αυτή δεν παίζει καλά εάν αλλάζετε μετά από την Ελληνική διάταξη.

Τρόπος γραφής:

Για να γράψετε hiragana απλά δείτε το Πινακάκι που είναι στον σύνδεσμο: <a class=»postlink» href=»https://en.wikipedia.org/wiki/Hiragana#Table_of_hiragana»>https://en.wikipedia.org/wiki/Hiragana# … f_hiragana</a> (Εκεί που αναγράφει: «Table of hiragana») και απλά γράψτε με λατινικούς χαρακτήρες (ρομάντζι – ロマン字) και πατώντας Enter το μετατρέπει σε Hiragana. Για να γίνουν σε kanji απλά πατάτε στο space πριν πατήσετε enterν ε΄αν δεν είναι αυτό που θέλετε να γράψετε πατάτε space πολλές φορές μέχρι να βρεθεί η διαθέσιμη.

πχ. Για την λέξη たべもの (Μετάφραση: φαγώσιμα αντικείμενα) πληκτρολογείτε tabemono + Enter ενώ για να εμφανιστεί έτσι (με κάντζι) 食べ物 πληκτρολογείτε tabemono + Space + Enter.

Ενώ η εναλλαγή με κατακάνα γίνετε με τον τρόπο που λέει η παρακάτω εικόνα:
<img class=»alignnone size-full wp-image-843″ src=»https://pcmagas.files.wordpress.com/2016/06/1466409148.png» alt=»1466409148″ width=»1118″ height=»349″ />

Ακόμη για να δείτε τι πρέπει να πληκτολογείτε για να γράψετε katakana θα το δείτε στο: <a href=»https://en.wikipedia.org/wiki/Katakana#Table_of_katakana»>https://en.wikipedia.org/wiki/Katakana#Table_of_katakana</a&gt;. Αλλά έχει και κάποιιους έξτρα συνδιασμούς που δεν αναφέρονται στον πίνακα (βλ. παρακάτω).
<h2>Προσοχή:</h2>
Πολλές φορές ο χαρακτήρας は(ha) διαβάζεται σαν wa.
Όμως για να γράψετε προτάσεις όπως πχ:
私はげんきです。 (Μετάφραση: Είμαι καλά στην υγεία μου.)
Πληκτρολογείτε :
Watashi + Space+Enter+ha+enter+genki+enter+desu+.

(Δώστε βάση στα έντονα γράμματα στο παραπάνω παράδειγμα)

Ομοίως και για το を(wo) που πολλές φορές διαβάζεται σαν ο.
πχ. 私はすしをたべました。 (Μετάφραση: Εγώ έφαγα σούσι.)
Πληκτρολογείτε:
Watashi+space+enter+sushi+enter+wo+tabemashita+enter+.

Ακόμη πολλές φορές θέλουμε να βάλουμε ένα μικρό つ όταν η λέξη κατά την ανάγνωση χρειάζεται μια παύση. Όπως στην λέξη けっこん (Μετάφραση γάμος) απλά πληκτρολογούμε τον ήχο που κάνει παύση. Αυτός ο τρόπος ισχύει και για κατακάνα.
πχ. Για την λέξη けっこん πληκτρολογούμε kekkon+enter. Ομοίως και σε παρόμοιες λέξεις όπως ろっぴゃく πληκτρολογούμε roppyaku+enter.

Ακόμη σε Κατακάνα έχουμε και κάποιους έξτρα συνδυασμούς χαρακτήρων όπως チィ ( διαβάζετε τι ). Εάν γράψουμε ti θα μας βγεί チ γι αυτό γράφουμε tyi .
<blockquote>Ένας καλός μνημονικός κανόνας είναι ότι εάν δεν βγαίνει ο σωστός συνδυασμός πριν το πρώτο γράμμα του συνδυασμού βάλε ένα y. Πχ. Στο προηγούμενο παράδειγμά μας το πρώτο γράμμα είναι το t και η αντιστοιχία σε ρομάντζι είναι ti (όπως διαβάζουμε πάντα) ε μετά το τ βάζουμε ένα y.</blockquote>

Ακόμη για να δείτε τι πρέπει να πληκτρολογήσουμε προκειμένου να προκειμένου να εμφανιστεί το κατάλληλο hiragana/katakana πρέπει να ακολουθήσετε τα κάτωθι βήματα:

Πρώτα αλλάξτε σε Ιαπωνική διάταξη και στο μενού αλλαγής γλώσσας επιλέξτε την επιλογή «Προτιμήσεις Anthy»:

Μετά στο παράθυρο που έχει ανοξει επιλέξτε «Typing Method» και μετά το κουμπί με τις 3 τελείες εκεί που αναγράφει «Πίνακας πλήκτρων Ρομάτζι»:

Ύστερα στο παράθυρο που ανοίγει θα δείτε την λίστα του τι πρέπει να πληκτρολογήσετε και τι θα εμφανίσει:

Πλέον μπορείτε να γράψετε Ιαπωνικά και το πολυπόθητο Lovwe Letter στην sempai σας!!!!!

Εντοπισμός documentation της βιβλιοθήκης libcrypt της OpenSSL για υπάρχουσες μεθόδους σε διανομές GNU/Linux.

Στο master thesis μου έπρεπε να κάνω ένα demo που να υλοποιεί ένα group key agreement. Μετά από πολύ ψάξιμο κατέληξα στην OpenSSL λόγο ότι έχει low level apis για να αναπτύσσεις ΚΑΙ δικό σου κρυπτογραφικό πρωτόκολλο.

Παρόλα αυτά υπήρχε δύσκολο-προς-εντοπισμό documentation έτσι το παρόν άρθρο το χρησιμοποιώ σαν index για το τι πρέπει να δώσω στην εντολή man ή που να πάω προκειμένου να μπορέσω να βρω πως χρησιμοποιείτε οι functions της βιβλιοθήκης.

  1. Getting Started βασική χρήση: Σύνδεσμος
  2. Diffie Hellman: Μεταβείτε σε αυτήν την σελίδα κάντε copy το όνομα μιας μεθόδου και σε τερματικό δώστε:
    man ^paste_την_function_που_κάνατε_copy_εδώ^
  3. BigNum για αριθμητική αριθμών για που λαμβάνουν μεγάλο χώρο στην μνήμη πχ.1024 ή 2048 bit ακεραίων:
    1. Όλες oι functions καταλογραφημένες είναι στο αποτέλεσμα της εντολής:
      man bn
    2. Για εκάστοτε function αναζητήστε:
      man ^όνομα_function_προηγούμενου_βήματος^
  4. Επίσημο Documentation για όλες της μεθόδους εδώ. Για εντοπισμό εγκατεστημένης έκδοσης δίνετε στο τερματικό:
    openssl version

Επικοινωνία με το πρωτόκολλο Xmpp μέσω XMPP.js: Προβλήματα και workaround.

Ο παρακάτω οδηγός είναι υπό συχνή ανανέωση καθώς καταγράφω της εμπειρίες μου όπως αναπτύσσω εφαρμογές με την βιβλιοθήκη xmpp.js

Στο master thesis μου έπρεπε να αναπτύξω μια εφαρμογή σε electron και Node.js που ουσιαστικά ήταν ένας xmpp client. Κατά την ανάπτυξη αυτής συνάντησα τα εξής προβλήματα αξιοποιώντας αυτήν την βιβλιοθήκη, τα οποιά στην συνέχεια σας δείχνω πως τα έχω επιλύσει.

Σύμφωνα με την τεκμηρίωση της βιβλιοθήκης ο συνιστώμενος κώδικας είναι ο εξής:



const xmpp = client({
service: 'xmpp://example.com',
domain: 'example',
username: 'user',
password: 'password',
})

xmpp.on('error', err => {
console.error('❌', err.toString())
})

xmpp.on('offline', () => {
console.log('🛈', 'offline')
})

xmpp.on('online', async address => {
console.log('🗸', 'online as', address.toString())

// Sends a chat message to itself
const message = xml(
'message',
{type: 'chat', to: address},
xml('body', 'hello world')
)
xmpp.send(message)
})

xmpp.on('stanza', stanza => {
console.log('⮈', stanza.toString())
xmpp.stop()
})

xmpp.start()
 Όμως έτσι σκέτος μου παρουσιάζει το εξής πρόβλημα, λόγο ότι  by default ενεργοποιεί SSL/TLS συνδέσεις, δεν μου επιτρέπει να διαχειρηστώ την περίπτωση που η SSL/TLS σύνδεση χρησιμοποιεί Self-signed πιστοποιητικά. Αυτό είναι γενικότερο θέμα της Node.js στον τρόπου που διαχειρίζεται το SSL. Λύνετε απλά θέτοντας την μεταβλητή περιβάλλοντος NODE_TLS_REJECT_UNAUTHORIZED στην τιμή 0. Πέρα από τις εντολές κονσόλας npm κλπ κλπ μπορεί να γίνει και μέσω κώδικα javascript, απλά προσθέστε στην αρχικό script που εκτελεί η εφαρμογή σας την παρακάτω γραμμή κώδικα:
process.env.NODE_TLS_REJECT_UNAUTHORIZED=0

Καλή ιδέα είναι να εκτελείτε η παραπάνω όταν είστε σε περιβάλλον ανάπτυξης και μόνο.

Πέρα από αυτό όταν κάνεις έναν client πρέπει να μπορείς να εμφανίζεις τουλάχιστον τον κατάλληλο μήνυμα είτε στον τελικό χρήστη είτε στον sysadmin έτσι πρέπει να διαχειρίζεσε κατάστάσεις όπως:

  • Ο χρήστης δίνει λάθος server ή o client δεν μπορεί να επικοινωνήσει στον server.
  • Ο χρήστης δίνει λάθος credentials.

Προσωπικά λόγο της φύσης της Node.js ο τρόπος που μπορούσα να το διαχειριστώ είναι ελέγχοντας μέσω regular expression (well μπορεί να μην σου αρέσει αλλά θέλοντας και μη πρέπει να μάθεις να γράφεις PCRE συμβατές regular expressions) το μήνυμα του σφάλματος. Ένα snippet κώδικα από την εφαρμογή μου που χρησιμοποιεί electron (που έχει ενσωματωμένη nodejs) είναι:

const errorRegex = {
DNS_NOT_FOUND: /^getaddrinfo ENOTFOUND/,
AUTH_FAILED: /^not-authorized/,
}; 
xmpp.on('error', (err) => {
  console.error('Error occured', err.message, Object.getPrototypeOf(err));
  if (errorRegex.DNS_NOT_FOUND.test(err.message)) {
      console.error('Connection Error', `The provided server ${connectionInfo.service} does not exist.`);
     // Add handling stuff here
     destructClient(xmpp);
  } else if (errorRegex.AUTH_FAILED.test(err.message)) {
    console.error('Authentication Error', 'The provided username and password are not valid');
    // Add further handling here
    destructClient(xmpp);
  }
});

Ουσιαστικά ανάλογα με το ποιο regular expression ορισμένο στο αντικείμενο errorRegex εφαρμόζω τον κατάλληλο έλεγχο.

Ακόμη εν λόγο βιβλιοθήκη κάνει αυτόματες επανασυνδέσεις, και το κάνει ΕΠ’ ΑΠΕΙΡΟΝ, πράγμα που δίνει άσχημο user experience στον τελικό χρήστη. Γι αυτό το περιορίζω σε 10 προσπάθειες που με το παρακάτω κομμάτι κώδικα:

let connectionCounter = 10;
xmpp.reconnect.on('reconnecting', () => {
  if (connectionCounter===0) {
    destructClient();
  }
  connectionCounter-=1;
})

Ουσιαστικά κάνω abort με xmpp.stop() που καλείτε εντός της destructClient(). Για μήνυμα σφάλματος δοκιμάστε το να το εκτυπώσετε στο event error:

xmpp.on('error', (e)=>{
 if (err.code === 'ECONNREFUSED' && connectionCounter === 0) {
   dialogsHelper.errorDialog('Connection Error', `Failed to connect into ${err.address}.`);
 }
}

Αξιοδημείωτε δε είναι ότι η διεύθυνση σύνδεσης έρχετε μαζί με το error όπως και ο τύπος του error στη μεταβλητή στιγμιότυπου error.

Επιπλέων ένα θέμα είναι ότι θέλω να τρέχω έναν κώδικα μια φορά όταν ο χρήστης κάνει login, για κάποιο λόγο η βιβλιοθήκη καλεί 2 φορές το event login, όμως δεν θέλουμε να τρέχουν κάποια πράγματα 2 φορές έτσι θα πρέπει να ορίζουμε κάποια μορφής flag που να μην επιτρέπει την εκτέλεση κάποιων κομματιών κώδικα 2 φορές (πχ. να εμφανίζει στον τελικό χρήστη δύο φορές ένα μήνυμα σύνδεσης):


let flag=false

//Some code goes here
xmpp.on('offline', () => {
 flag=false;
}

xmpp.on('online',(address) => {
  if(!flag){
   flag=true;
   console.log(`You logged in as ${address}`); 
  }
})

Επιπλέον τα μηνύματα που αποστέλλονται μέσω XMPP ονομάζονται stanzas και υπάρχονυ πάρα πολλά είδη. Για κάθε ένα είδος ορίζω και μια ξεχωριστή function όπως βλέπετε στον παρακάτω κώδικα:

xmpp.on('stanza',(stanza)=> {
  try {
 if(presenceReply(stanza) !== false) return;
 if(handleRoster(stanza) !== false) return;
 // Add your function here
 } catch(e) {
   console.error(e);
 }
});

Αυτή η δομή λόγο όχι χρησιμοποιεί πολλές function για να επεξεργαστεί καταλλήλως το εισερχόμενο μύνημα πρέπει στην αρχή να ελέγχετε ο τύπος με τον εξής τρόπο πχ στην function presenceReply:

const presenceReply = (stanza) => {
  if(!stanza.is('presence')) return false;
  if(loginAddress.bare().equals(from.bare())) return false;
  
  const from = jid(stanza.attrs.from);
  const message = xml('presence', { to: stanza.attrs.from });
  console.log('Sent To', stanza.attrs.from);
  sendMessage(message);
  return true;
};

Όπως βλέπουμε καλύτερα να ελέγχουμε εάν ο τύπος ΔΕΝ είναι αυτός που ζητάμε και να επιστρέφουμε, από προσωπική εμπειρία αυτό είναι ένας bulletrpoof τρόπος να αποτρέπει στο να σπάει το πρόγραμμα σε ΠΟΛΛΕΣ περιπτώσεις. Ακόμη όπως βλέπετε όταν το μύνημα δεν είναι ο κατάλληλος τύπος επιτρέφουμε false και την τιμή αυτή την ελέγχουμε στην callback το event ‘stanza’, εάν ελέγχθηκε τότε προχωράμε στην επόμενη function η ιδέα είναι ότι δεν θέλουμε να εκτελέσουμε κάποια function εάν ήδη έχουμε επεξεργαστεί το μήνυμα.

Τέλος ο έλεγχος γίνετε ελέγχοντας εάν η τιμή ΔΕΝ είναι false με το σύμβολο !== λόγο ότι με αυτόν τον τρόπο σε επιτιχία μπορούμε επιτρέπουμε να ΜΗΝ επιστρέφει τιμή,
εναλλακτική προσέγγιση είναι η χρήση reqular expression που επιστρέφετε με την μέθοδο stanza.toString(). Ακόμη δε, χρήζει σημείωσης, όλη η σειρά των ifs είναι σε ένα try ... catch block επιτρέποντας όποιο σφάλμα συμβαίνει να ΜΗΝ κρασάρει όλη την εφαρμογή αλλά να μένει και να διαχειρίζεται τοπικά. Ενδεικτικά βάζω console.error αλλά μπορεί στην θέση του να οποιοδήποτε κομμάτι κώδικα.

Ακόμη όταν θέλετε να τραβήξετε όλους τους φίλους και τους κάνετε render, καλό είναι να ακολουθήσετε την εξής διαδικασία (δοκιμασμένη σε electron που ουσιαστικά είναι ένας browser και nodejs που σε αυτόν τρέχω και την xmpp.js άρα δεν υπάρχει communication overhead):

  1. Αποστείλετε ένα roster request.
  2. Όταν το λάβετε κάντε το render.
  3. Όταν γίνει render αποστείλετε ότι είστε online με το δικό σας presence

Για ποιο ολοκληρωμένη εικόνα δείτε την παρακάτω εικόνα, σε περίπτωση web client συνηστώ η χρήση websocket λόγο φόρτου επικοινωνίας.
Διαδικασία μεταξύ Application Backend και Ui για συγχρονισμό και σωστή ενημέρωση αυτού.

Ακόμη δε κατά το event presense response όπου δείχνετε στην πάνω εικόνα να αποστέλλετε ολόκληρο το roster εφόσον το έχετε ενημερώσει εσωτερικά στο backend της εφαρμογής σας (πχ. σε μια in-memory database ή σε ένα object vatiable). Ακόμα θεμιτό είναι να μαζεύετε όσα περισσότερα status updates μπορείτε εάν σας νοιάζει το πάρε-δώσε μεταξύ ui και εφαρμογής. Ακόμη δε να έχετε στον νου σας ότι ένα participant στο roster μπορεί να είναι συνδεδεμένος σε πολλαπλές συσκευές και το status είναι ανά συσκευή.

Κατά την γνώμη μου είναι hacky ο παραπάνω τρόπος αλλά είναι η μόνη βιβλιοθήκη η οποία αναπτύσσετε προς το παρόν και συντηρείτε ενεργά (περίοδο που γράφετε το άρθρο). Αλλά λόγο ότι το API είναι βασικό και σπαρτιάτικο σε "μαθαίνει" xmpp