Enviado em 20/03/2018 - 10:03h
Prezados,#define DIGIT "0123456789" #define LOWER "abcdefghijklmnopqrstuvwxyz" #define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define ALPHA UPPER LOWER #define ATEXT ALPHA DIGIT "!#$%&'*+/=?^_`{|}~-" // Note que o hífen está no final da lista. #define DOT_ATOM_TEXT "[" ATEXT "]+(?:\\.[" ATEXT "]+)?" // "(?: ... )" agrupa pedaços sem criar back-references. // "[...]" é uma forma sucinta de informar conjunto de caracteres válidos. #define DOT_ATOM "(?:" DOT_ATOM_TEXT ")" #define LOCAL_PART DOT_ATOM #define DOMAIN_ DOT_ATOM #define ADDR_SPEC "(" LOCAL_PART ")@(" DOMAIN_ ")" // Aqui eu uso agrupamento com back-references, para poder ter a opção // de testar os valores de nome e domínio (validade, não apenas sintaxe). #define MAILBOX "^(?:" ADDR_SPEC ")$" #define ADDRESS "(?:" MAILBOX ")" #include <regex> #include <string> #ifdef VALIDATE_DOMAIN #include <dns.h> // Parte do pacote libowfat-dev. #include <stralloc.h> // Parte do pacote libowfat-dev. #endif #ifdef VALIDATE_LOCAL_PART #include <set> extern std::set<std::regex> rejected_username_res; #endif using namespace std; const regex address_re(ADDRESS); // Tipo que indica o motivo de um endereço ser eventualmente inválido. enum class invalid_addr_reason { is_valid, format, local_part, domain }; // Função que testa se um endereço de e-mail é válido ou não. Se for, a // função retorna true; caso contrário, retorna false e, se o segundo parâmetro // tiver sido usado com um argumento não-nulo, coloca na região apontada por // ele um valor indicando a causa do erro. bool is_valid_address(const string &addr, invalid_addr_reason *p_reason=nullptr){ smatch parts; if(!regex_match(addr, parts, address_re)){ if(p_reason) *p_reason=invalid_addr_reason::format; return false; } // A sintaxe está OK. Agora examina se o domínio existe e se o nome do // usuário remoto é suspeito. #ifdef VALIDATE_DOMAIN // Para o domínio ser válido, deve haver no DNS um registro do tipo MX ou // um registro do tipo A (IPv4) ou AAAA (IPv6). static stralloc domain={0}, response={0}; stralloc_copys(&domain, parts[2].str().c_str()); if( (dns_mx(&response, &domain)!=0 || response.len==0) && (dns_ip4(&response, &domain)!=0 || response.len==0) && (dns_ip6(&response, &domain)!=0 || response.len==0) ){ if(p_reason) *p_reason=invalid_addr_reason::domain; return false; } #endif #ifdef VALIDATE_LOCAL_PART // Exemplo de tratamento: rejected_username_res é um conjunto de expressões // regulares contendo nomes que não devam ser aceitos como parte do endere- // ço. Esse conjunto poderia conter expressões regulares para impedir o // uso de nomes reservados, tais como "postmaster", "mailerdaemon", "root", // etc., palavrões (e.g. ".*\b(?:lista|de|palavrões|aqui)\b.*") e outros // nomes embaraçosos. Alternativamente, algum outro critério ou algoritmo // poderia ser usado. const string local_part=parts[1]; for(const auto &invalid_name_re: rejected_username_res) if(regex_match(local_part, invalid_name_re)){ if(p_reason) *p_reason=invalid_addr_reason::local_part; return false; } #endif // Se chegou a este ponto, não achou falha no endereço. Assim sendo, // consideramo-lo válido. if(p_reason) *p_reason=invalid_addr_reason::is_valid; return true; }
Enviado em 20/03/2018 - 11:30h
Segue uma outra versão do mesmo código, que depende menos de macros (uma delas, inclusive, teve de usar o horrível nome “DOMAIN_”, porque DOMAIN já está em uso em sistemas que mantenham compatibilidade com o UNIX System V, o que inclui o Linux).#include <regex> #include <set> #include <string> using namespace std; namespace rfc5322_subset { const string digit{"0123456789"}; const string lower{"abcdefghijklmnopqrstuvwxyz"}; const string upper{"ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; const string alpha{upper+lower}; const string atext{alpha+digit+"!#$%&'*+/=?^_`{|}~-"}; // Note que o hífen está no final da lista. const string dot_atom_text{"["+atext+"]+(?:\\.["+atext+"]+)?"}; // "(?: ... )" agrupa pedaços sem // criar back-references. // "[...]" é uma forma sucinta // de informar conjunto de // caracteres válidos. const string dot_atom{"(?:"+dot_atom_text+")"}; const string local_part{dot_atom}; const string domain{dot_atom}; const string addr_spec{"("+local_part+")@("+domain+")"}; // Aqui eu uso agrupamento com // back-references, para poder ter // a opção de testar os valores de // nome e domínio (validade, e // não apenas sintaxe). const string mailbox{"^(?:"+addr_spec+")$"}; const string address{"(?:"+mailbox+")"}; } #ifdef VALIDATE_DOMAIN #include <dns.h> // Parte do pacote libowfat-dev. #include <stralloc.h> // Parte do pacote libowfat-dev. #endif #ifdef VALIDATE_LOCAL_PART extern std::set<std::regex> rejected_username_res; #endif const regex address_re(rfc5322_subset::address); // Tipo que indica o motivo de um endereço ser eventualmente inválido. enum class invalid_addr_reason { is_valid, format, local_part, domain }; // Função que testa se um endereço de e-mail é válido ou não. Se for, a // função retorna true; caso contrário, retorna false e, se o segundo parâmetro // tiver sido usado com um argumento não-nulo, coloca na região apontada por // ele um valor indicando a causa do erro. bool is_valid_address(const string &addr, invalid_addr_reason *p_reason=nullptr){ smatch parts; if(!regex_match(addr, parts, address_re)){ if(p_reason) *p_reason=invalid_addr_reason::format; return false; } // A sintaxe está OK. Agora examina se o domínio existe e se o nome do // usuário remoto é suspeito. #ifdef VALIDATE_DOMAIN // Para o domínio ser válido, deve haver no DNS um registro do tipo MX ou // um registro do tipo A (IPv4) ou AAAA (IPv6). static stralloc domain={0}, response={0}; stralloc_copys(&domain, parts[2].str().c_str()); if( (dns_mx(&response, &domain)!=0 || response.len==0) && (dns_ip4(&response, &domain)!=0 || response.len==0) && (dns_ip6(&response, &domain)!=0 || response.len==0) ){ if(p_reason) *p_reason=invalid_addr_reason::domain; return false; } #endif #ifdef VALIDATE_LOCAL_PART // Exemplo de tratamento: rejected_username_res é um conjunto de expressões // regulares contendo nomes que não devam ser aceitos como parte do endere- // ço. Esse conjunto poderia conter expressões regulares para impedir o // uso de nomes reservados, tais como "postmaster", "mailerdaemon", "root", // etc., palavrões (e.g. ".*\b(?:lista|de|palavrões|aqui)\b.*") e outros // nomes embaraçosos. Alternativamente, algum outro critério ou algoritmo // poderia ser usado. const string local_part=parts[1]; for(const auto &invalid_name_re: rejected_username_res) if(regex_match(local_part, invalid_name_re)){ if(p_reason) *p_reason=invalid_addr_reason::local_part; return false; } #endif // Se chegou a este ponto, não achou falha no endereço. Assim sendo, // consideramo-lo válido. if(p_reason) *p_reason=invalid_addr_reason::is_valid; return true; }
Enviado em 20/03/2018 - 12:10h
Enviado em 20/03/2018 - 12:21h
Resolver problemas de Internet
Como compartilhar a tela do Ubuntu com uma Smart TV (LG, Samsung, etc.)
Descritores de Arquivos e Swappiness
Como converter imagens PNG/JPEG para SVG em linha de comando
Fez porcaria no teu repositório Git? Aprenda a restaurar uma versão anterior do seu código!
Restaurando Fontes de Download do Hydra no Linux
Atualizando "na marra" o YT-DLP quando começa a dar erro de downloads
Como instalar o WPS com interface e corretor ortográfico em PT-BR no Arch Linux
Bluetooth CSR 4.0 Dongle (Alternativo) (4)
Controle do PS5 no Linux Mint funciona? [RESOLVIDO] (6)