LCOV - code coverage report
Current view: top level - core/idn - SPIdn.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 17 40 42.5 %
Date: 2024-05-12 00:16:13 Functions: 4 8 50.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #include "SPIdn.h"
      25             : 
      26             : #ifdef WIN32
      27             : #include "SPPlatformUnistd.h"
      28             : #include "SPString.h"
      29             : #include "winnls.h"
      30             : #else
      31             : #include "unicode/uidna.h"
      32             : #endif
      33             : 
      34             : namespace STAPPLER_VERSIONIZED stappler::idn {
      35             : 
      36             : using HostUnicodeChars = chars::Compose<char, chars::CharGroup<char, CharGroupId::Alphanumeric>,
      37             :                 chars::Chars<char, '.', '-'>, chars::Range<char, char(128), char(255)>>;
      38             : 
      39             : using HostAsciiChars = chars::Compose<char, chars::CharGroup<char, CharGroupId::Alphanumeric>,
      40             :                 chars::Chars<char, '.', '-'>>;
      41             : 
      42             : template <typename Interface>
      43        1875 : auto _idnToAscii(StringView source, bool validate) -> typename Interface::StringType {
      44        1875 :         if (source.empty()) {
      45           0 :                 return typename Interface::StringType();
      46             :         }
      47             : 
      48        1875 :         if (validate) {
      49        1000 :                 StringView r(source);
      50        1000 :                 r.skipChars<HostUnicodeChars>();
      51        1000 :                 if (!r.empty()) {
      52           0 :                         return typename Interface::StringType();
      53             :                 }
      54             :         }
      55             : 
      56             : #ifdef WIN32
      57             :         auto in_w = string::toUtf16<memory::StandartInterface>(source);
      58             :         wchar_t punycode[256] = { 0 };
      59             :         int chars = IdnToAscii(0, (const wchar_t *)in_w.data(), -1, punycode, 255);
      60             :         if (chars) {
      61             :                 return string::toUtf8<Interface>((char16_t *)punycode);
      62             :         }
      63             : #else
      64        1875 :         char buf[1_KiB] = { 0 };
      65        1875 :         UErrorCode code = U_ZERO_ERROR;
      66        1875 :         auto retLen = u_nameToASCII_UTF8(UIDNA_NONTRANSITIONAL_TO_ASCII, source.data(), source.size(), buf, 1_KiB, nullptr, &code);
      67        1875 :         if (retLen > 0 && code == U_ZERO_ERROR) {
      68        1875 :                 typename Interface::StringType ret(buf, retLen);
      69        1875 :                 return ret;
      70        1875 :         }
      71             : 
      72             :         /*char *out = nullptr;
      73             :         auto err = idn2_to_ascii_8z(source.data(), &out, IDN2_NFC_INPUT|IDN2_NONTRANSITIONAL);
      74             :         if (err == IDN2_OK) {
      75             :                 typename Interface::StringType ret(out);
      76             :                 free(out);
      77             :                 return ret;
      78             :         }*/
      79             : #endif
      80           0 :         return typename Interface::StringType();
      81             : }
      82             : 
      83             : template <typename Interface>
      84           0 : auto _idnToUnicode(StringView source, bool validate) -> typename Interface::StringType {
      85           0 :         if (source.empty()) {
      86           0 :                 return typename Interface::StringType();
      87             :         }
      88             : 
      89           0 :         if (validate) {
      90           0 :                 StringView r(source);
      91           0 :                 r.skipChars<HostAsciiChars>();
      92           0 :                 if (!r.empty()) {
      93           0 :                         return typename Interface::StringType();
      94             :                 }
      95             :         }
      96             : 
      97             : #ifdef WIN32
      98             :         auto in_w = string::toUtf16<memory::StandartInterface>(source);
      99             :         wchar_t unicode[256] = { 0 };
     100             :         int chars = IdnToUnicode(0, (const wchar_t *)in_w.data(), int(in_w.size()), unicode, 255);
     101             :         if (chars) {
     102             :                 return string::toUtf8<Interface>((char16_t *)unicode);
     103             :         }
     104             : #else
     105           0 :         char buf[1_KiB] = { 0 };
     106           0 :         UErrorCode code = U_ZERO_ERROR;
     107           0 :         auto retLen = u_nameToUnicodeUTF8(0, source.data(), source.size(), buf, 1_KiB, nullptr, &code);
     108           0 :         if (retLen > 0 && code == U_ZERO_ERROR) {
     109           0 :                 typename Interface::StringType ret(buf, retLen);
     110           0 :                 return ret;
     111           0 :         }
     112             : 
     113             :         /*char *out = nullptr;
     114             :         auto err = idn2_to_unicode_8z8z(source.data(), &out, 0);
     115             :         if (err == IDN2_OK) {
     116             :                 typename Interface::StringType ret(out);
     117             :                 free(out);
     118             :                 return ret;
     119             :         }*/
     120             : #endif
     121           0 :         return typename Interface::StringType();
     122             : }
     123             : 
     124             : 
     125             : template <>
     126        1675 : auto toAscii<memory::PoolInterface>(StringView source, bool validate) -> memory::PoolInterface::StringType {
     127        1675 :         return _idnToAscii<memory::PoolInterface>(source, validate);
     128             : }
     129             : 
     130             : template <>
     131         200 : auto toAscii<memory::StandartInterface>(StringView source, bool validate) -> memory::StandartInterface::StringType {
     132         200 :         return _idnToAscii<memory::StandartInterface>(source, validate);
     133             : }
     134             : 
     135             : template <>
     136           0 : auto toUnicode<memory::PoolInterface>(StringView source, bool validate) -> memory::PoolInterface::StringType {
     137           0 :         return _idnToUnicode<memory::PoolInterface>(source, validate);
     138             : }
     139             : 
     140             : template <>
     141           0 : auto toUnicode<memory::StandartInterface>(StringView source, bool validate) -> memory::StandartInterface::StringType {
     142           0 :         return _idnToUnicode<memory::StandartInterface>(source, validate);
     143             : }
     144             : 
     145             : }

Generated by: LCOV version 1.14