Rss

  • youtube
  • linkedin
  • google

Servidor de Email –; Part 3 ; Dovecot

This is the third part of the process of creating the mail server on a CentOS 8. If you came here by accident, You should read first the previous publications

Part 1 ; Instalação dos Pacotes

Part 2 ; Configurar MariaDB

Dovecot is an MDA (Mail Delivery Agent) means is an agent that transport messages from Postfix to virtual message boxes. In this section we will configure the Dovecot installation to force users to use SSL when they connect, in this way never sending passwords in plain text mode.

I always like to keep the original files of any definition for if I end up getting lost while changing settings. I can say that this step is not needed if you are doing this tutorial entirely, However, If you already have a previous configuration and is just improving it I strongly suggest you make copies of your files.

In our case, the configuration files will be in /etc/dovecot/conf.d/. We can then make copies with the command:



Continue Reading >>

Servidor de Email –; Part 2 ; MariaDB

This is the second part of the process of creating the mail server on a CentOS 8. If you came here by accident, You should read first the previous publication on the Instalação dos Pacotes

Why use MariaDB/MySQL?

First of all I must clarify that I prefer to use PostgreSQL instead of MariaDB/MySQL for many reasons, However, There is one that weighs against the use of PostgreSQL in a unified server with WordPress and E-mail services is the simple fact that WP does not have native support for PostgreSQL. You can have more information on this topic on the official WordPress documentation This link. How am I basing on personal experience to write this document and also for small services, I'm using the most common and most accessible. If the use of PostgreSQL is of your interest, You can consult this document later where I'll show you how to migrate from MariaDB for PostgreSQL.

Configuring MariaDB/MySQL

Assuming that you are following the steps of this manual, You'll be with an installation of MariaDB still not configured. If you already have a functional installation, You can skip to the next step.



Continue Reading >>

Datatables + HTML 5 Export Buttons + Laravel-Mix (Webpack)

In the last days, I have experienced a problem trying to use Datatables and Bootstrap 4 with support for exporting results to Excel and PDF using Laravel-Mix. After hours and hours trying to put all scripts to work together, I finally win. So, I decide to write this little how to for those with same kind of troubles.



Continue Reading >>

J5 Links

Here are some useful links to Samsung J5 cell Phone.

Google Account verification Bypass

Download Odin 3

Odin allows you to update your Android firmware without fuss.

Odin3 is a free PC (Windows) application which can flash (and root) some Android-based cell phones.

With Odin3, you can flash roms in your Samsung cell phone. You can install any supported version of the Android OS on your smartphone before your phone manufacturer has released an update, putting you on the bleeding edge of software. Once your phone has been rooted

Continue Reading >>

Using jQueryMask Plugin to format dates in different patterns

jQuery Mask Plugin is a great Javascript library to format fields for presentation and/or to force a properly input by users.

Here, I show how to deal with input or another HTML element to display dates when the source date has a different format from target element.

Example:

  • We have a datetime with Year-Month-Day Hour:Minute:Seconds and need to show only the Year/Month/Day part.
  • We have da date in Year-Month-Day and need to format to Day/Month/Year.

jQueryMask is very simple to use. It do not need to much to mask whatever you need. Take a look at examples on his website.

If you need to format a simple date field (even in a non-input element), just use the code below.

jQuery('[data-role="date"]).mask("TC99/M9/D9", {
        placeholder: "____/__/__",
        translation: {
            "D": {pattern: /[0-3]/, optional: false, recursive: true},
            "M": {pattern: /[01]/, optional: false, recursive: true},
            "T": {pattern: /[12]/, optional: false, recursive: true},
            "C": {pattern: /[09]/, optional: false, recursive: true}
        }
    });

The code above can mask and pre-validate dates in YEAR/MONTH/DAY format.

With an input like

<input type="text" data-role="date" value="2018-06-11 15:47" />

would be changed his value to 2018/06/11.

If you try to type another date (after clear, of course) you cannot begin with a number different from 1 or 2. This reason is that our mask have a translation to be done when allowing chars. If the pattern does not match, the char is erased.

The meaning of “TC99/M9/D9” mask is:

  • Must begin with 1 or 2 (Translation T: /[12]/ – Custom format)
  • Must have number 0 or 9 (Translation C: /[09]/ – Custom format)
  • Must have a number (any) (Translation 9 – MaskPlugin Core format)
  • Must have a number (any) (Translation 9 – MaskPlugin Core format)
  • A slash will be added automatic ( / )
  • Must have number 0 or 1 (Translation M: /[01]/ – Custom format)
  • Must have a number (any) (Translation 9: MaskPlugin Core format)
  • A slash will be added automatic ( / )
  • Must have number 0, 1, 2 or 3 (Translation D: /[0-3]/ – Custom format)
  • Must have a number (any) (Translation 9: MaskPlugin Core format)

Of course, there is no real validation. You can type “2999/19/39” and this is not a valid date, but is almost done.

So, to format in another way, just change mask parameter order.

But, if the source date is in a different pattern, like MONTH/DAY/YEAR, the mask do not work. The date output for “06/11/2018 15:40” will be weird “1018/15/0“.

To handle different date formats will be needed more than simple mask. We will need a function.

Look the code below

        var maskBehaviorDateTime = function (val, e, field) { // This function must return a MASK
                    var msk = "TC99/M9/D9"; // Our desired format
                    var v = field.is('input') ? field.val() : field.text(); // is a input or another html element??
                    v = v.replace(/\D/g, ''); // stripe non digits
                    if (v != '') { // has value?
                        if ((/^[01]\d[0-3]\d\d{4}$/).test(v)) { //test if pattern match Month/Day/Year only
                            v = v.replace(/^(\d{4})(\d{2})(\d{2})$/, '$3/$2/$1');
                        } else if ((/^[01]\d[0-3]\d\d{4}[012]\d[0-5]\d$/).test(v)) { //test if pattern match Month/Day/Year Hour:Minute
                            v = v.replace(/^(\d{2})(\d{2})(\d{4})(\d{2})(\d{2})$/, '$3/$2/$1');
                            // If we need to show hour and minute, returned mask must be changed too
                            // v = v.replace(/^(\d{2})(\d{2})(\d{4})(\d{2})(\d{2})$/, '$3/$2/$1 $4:$5');
                            // msk = 'TC99/M9/D9 h9:m9'; // h and m must be exists in Translation options
                        }
                        field.is('input') ? field.val(v) : field.text(v);
                    }
                    return msk;
                },
                optionsDateTime = {
                    placeholder: "____/__/__",
                    translation: {
                        "D": {pattern: /[0-3]/, optional: false, recursive: true},
                        "M": {pattern: /[01]/, optional: false, recursive: true},
                        "T": {pattern: /[12]/, optional: false, recursive: true},
                        "C": {pattern: /[09]/, optional: false, recursive: true},
                        "h": {pattern: /[0-2]/, optional: true, recursive: true},
                        "m": {pattern: /[0-5]/, optional: true, recursive: true}
                    }
                };
        jQuery('[data-role="date"]').mask(maskBehaviorDateTime,  optionsDateTime);

Now we have two more Translation Pattern (h and m). h means that the n-index position must have numbers 0, 1 or 2 and m numbers between 0 and 5. Keep in mind that CASE matters.

With the above code, we can format and show date in several ways. just change .test() and .replace() pattern to fill your desired pattern.

This is the code that I am using to format Database datetime fields with YEAR-MONTH-DAY HOUR:MINUTE:SECOND in html elements with DAY/YEAR/MONTH HOUR:MINUTE

    var maskBehaviorDateTime = function (val, e, field) {
            // Caso já exista um valor, o formata no padrão dd/mm/yyyy com o opcional hh:mm:ss
            var msk = "TC99/M9/D9 h9:m9:s9";
            if (field.attr("data-original-value") == undefined) {
                var o = field.is('input') ? field.val() : field.text();
            } else {
                var o = field.attr("data-original-value");
            }
            v = o.replace(/\D/g, '');
            if (v != '') {
                field.attr("data-original-value") == undefined && field.attr("data-original-value", o);
                if ((/^[12][09]\d{2}[01]\d[0123]\d$/).test(v)) { // year/month/day
                    v = v.replace(/^(\d{4})(\d{2})(\d{2})$/, '$3/$2/$1');
                    msk = "D9/M9/TC99";
                } else  if ((/^[12][09]\d{2}[01]\d[0123]\d[012]\d[0-5]\d$/).test(v)) { // year/month/day hour:minute
                    v = v.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$3/$2/$1 $4:$5');
                    msk = "D9/M9/TC99 h9:m9";
                } else if ((/^[12][09]\d{2}[01]\d[0123]\d[012]\d[0-5]\d[0-5]\d$/).test(v)) { // year/month/day hour:minute:second
                    v = v.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$3/$2/$1 $4:$5:$6');
                    msk = "D9/M9/TC99 h9:m9:s9";
                }
                field.is('input') ? field.val(v) : field.text(v);
            }

            return msk;
        },
        optionsDateTime = {
            placeholder: "__/__/____",
            translation: {
                "D": {pattern: /[0-3]/, optional: false, recursive: true},
                "M": {pattern: /[01]/, optional: false, recursive: true},
                "T": {pattern: /[12]/, optional: false, recursive: true},
                "C": {pattern: /[09]/, optional: false, recursive: true},
                "h": {pattern: /[0-2]/, optional: true, recursive: true},
                "m": {pattern: /[0-5]/, optional: true, recursive: true},
                "s": {pattern: /[0-5]/, optional: true, recursive: true}
            },
        };
    jQuery('[data-role="date"]').mask(maskBehaviorDateTime,  optionsDateTime);

With an input like

<input type="text" data-role="date" value="2018-06-11 15:40">

Output will be

11/06/2018 15:40

Hope this help you!

Binding several values in PDO SQL Statement (PDOStatement)

Sometimes we need to search a single value through several columns when building SQL instructions.

Suppose the table below

  • [ENTITY_ONE]
    • ID
    • COLUMN_A
    • COLUMN_B
    • COLUMN_C
    • COLUMN_D
    • COLUMN_E

If we need search a single value on columns B,D and E we will need use the following instruction

SELECT ID, COLUMN_A,(...COLUMNS..), COLUMN_E 
FROM ENTITY_ONE WHERE COLUMN_B LIKE '%search_value%' OR COLUMN_D LIKE '%search_value%' OR COLUMN_E LIKE '%search_value%';

In PHP code we can do

$q = '%search_value%';
$sql = "SELECT * FROM ENTITY_ONE WHERE COLUMN_B LIKE '$q' OR COLUMN_D LIKE '$q' OR COLUMN_E LIKE '$q'; 
$pdo = new PDO($dsn, $user, $pass); 
$stmt = $pdo->query($sql);

Well, this can work but we know that isn’t the best approach. We need use Binding Values to avoid SQL injection and other malicious treats.

So, the code can be modified to

$q = '%search_value%'; 
$sql = "SELECT * FROM ENTITY_ONE WHERE COLUMN_B LIKE ? OR COLUMN_D LIKE ? OR COLUMN_E LIKE ?; 
$args = [$q, $q, $q]; // We need one entry for each "?" on instruction
$pdo = new PDO($dsn, $user, $pass); 
$stmt = $pdo->prepare($sql);
$stmt->execute($args);

Much better, but, when building complex SQL instruction, things can be confusing with lots of arguments and don’t forget: ORDER MATTERS.

Happily PDO can bind values in different order when using named bindings.

$q = '%search_value%'; 
$sql = "SELECT * FROM ENTITY_ONE WHERE COLUMN_B LIKE :first_arg OR COLUMN_D LIKE :second_arg OR COLUMN_E LIKE :third_arg; 

$pdo = new PDO($dsn, $user, $pass); 
$stmt = $pdo->prepare($sql); 
// One way
$args = [':first_arg' => $q, ':third_arg' =>$q, ':second_arg' => $q]; // We need one entry for each ":name" on instruction 
$stmt->execute($args); 
// Another way
$stmt->bindValue(':third_arg'. $q);
$stmt->bindValue(':first_arg', $q); 
$stmt->bindValue(':second_arg', $q);

$stmt->execute(); 

Hmm, seems that this isn’t good enough. We only change the use of 1-indexed placeholder to a :named placeholder. There’s no gain beyond of code readable and the possibility to bind in any order.

Yes, but now we can do the best approach when using one unique search term in several columns. We can use only one bind to one or more :named placeholders ’cause PDO is smart and clever. Look our final code here.

$q = '%search_value%'; 
$sql = "SELECT * FROM ENTITY_ONE WHERE COLUMN_B LIKE :unique_arg OR COLUMN_D LIKE :unique_arg OR COLUMN_E LIKE :unique_arg; 
$pdo = new PDO($dsn, $user, $pass); 
$stmt = $pdo->prepare($sql); 
// One way 
$args = [':unique_arg' => $q]; // We can bind all :name with only one term 
$stmt->execute($args); 
// Another way 
$stmt->bindValue(':unique_arg', $q); 
$stmt->execute(); 

Can save a lot of typing when writing many SQL instruction using same argument.