lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / sal / osl / unx / file_url.cxx
blob24fa04c7bfa6d7b8e258b05e0315a298a4d64214
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "file_url.hxx"
22 #include "system.hxx"
24 #include <cassert>
25 #include <stdexcept>
26 #include <limits.h>
27 #include <errno.h>
28 #include <strings.h>
29 #include <unistd.h>
31 #include <osl/file.hxx>
32 #include <osl/security.hxx>
33 #include <osl/diagnose.h>
34 #include <osl/thread.h>
35 #include <osl/process.h>
37 #include <rtl/character.hxx>
38 #include <rtl/uri.h>
39 #include <rtl/uri.hxx>
40 #include <rtl/ustring.hxx>
41 #include <rtl/ustrbuf.h>
42 #include <rtl/textcvt.h>
43 #include <sal/log.hxx>
45 #include "file_error_transl.hxx"
46 #include "file_path_helper.hxx"
48 #include "uunxapi.hxx"
50 /** @file
52 General note
54 This file contains the part that handles File URLs.
56 File URLs as scheme specific notion of URIs
57 (RFC2396) may be handled platform independent, but
58 will not in osl which is considered wrong.
59 Future version of osl should handle File URLs this
60 way. In rtl/uri there is already an URI parser etc.
61 so this code should be consolidated.
65 using namespace osl;
67 namespace {
69 // A slightly modified version of Pchar in rtl/source/uri.c, but without
70 // encoding slashes:
71 const sal_Bool uriCharClass[128] = {
72 false, false, false, false, false, false, false, false,
73 false, false, false, false, false, false, false, false,
74 false, false, false, false, false, false, false, false,
75 false, false, false, false, false, false, false, false,
76 false, true, false, false, true, false, true, true, // !"#$%&'
77 true, true, true, true, true, true, true, true, // ()*+,-./
78 true, true, true, true, true, true, true, true, // 01234567
79 true, true, true, false, false, true, false, false, // 89:;<=>?
80 true, true, true, true, true, true, true, true, // @ABCDEFG
81 true, true, true, true, true, true, true, true, // HIJKLMNO
82 true, true, true, true, true, true, true, true, // PQRSTUVW
83 true, true, true, false, false, false, false, true, // XYZ[\]^_
84 false, true, true, true, true, true, true, true, // `abcdefg
85 true, true, true, true, true, true, true, true, // hijklmno
86 true, true, true, true, true, true, true, true, // pqrstuvw
87 true, true, true, false, false, false, true, false}; // xyz{|}~
91 oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
93 OSL_FAIL("osl_getCanonicalName not implemented");
95 rtl_uString_newFromString(pustrValidURL, ustrFileURL);
96 return osl_File_E_None;
99 namespace {
101 oslFileError getSystemPathFromFileUrl(
102 OUString const & url, OUString * path, bool resolveHome)
104 assert(path != nullptr);
105 // For compatibility with assumptions in other parts of the code base,
106 // assume that anything starting with a slash is a system path instead of a
107 // (relative) file URL (except if it starts with two slashes, in which case
108 // it is a relative URL with an authority component):
109 if (url.isEmpty()
110 || (url[0] == '/' && (url.getLength() == 1 || url[1] != '/')))
112 return osl_File_E_INVAL;
114 // Check for non file scheme:
115 sal_Int32 i = 0;
116 if (rtl::isAsciiAlpha(url[0])) {
117 for (sal_Int32 j = 1; j != url.getLength(); ++j) {
118 auto c = url[j];
119 if (c == ':') {
120 if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
121 url.pData->buffer, j,
122 RTL_CONSTASCII_STRINGPARAM("file"))
123 != 0)
125 return osl_File_E_INVAL;
127 i = j + 1;
128 break;
129 } if (!rtl::isAsciiAlphanumeric(c) && c != '+' && c != '-'
130 && c != '.')
132 break;
136 // Handle query or fragment:
137 if (url.indexOf('?', i) != -1 || url.indexOf('#', i) != -1)
138 return osl_File_E_INVAL;
139 // Handle authority:
140 if (url.getLength() - i >= 2 && url[i] == '/' && url[i + 1] == '/')
142 i += 2;
143 sal_Int32 j = url.indexOf('/', i);
144 if (j == -1)
145 j = url.getLength();
146 if (j != i
147 && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
148 url.pData->buffer + i, j - i,
149 RTL_CONSTASCII_STRINGPARAM("localhost"))
150 != 0)
151 && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
152 url.pData->buffer + i, j - i,
153 RTL_CONSTASCII_STRINGPARAM("127.0.0.1"))
154 != 0))
156 return osl_File_E_INVAL;
158 i = j;
160 // Handle empty path:
161 if (i == url.getLength())
163 *path = "/";
164 return osl_File_E_None;
166 // Path must not contain %2F:
167 if (url.indexOf("%2F", i) != -1 || url.indexOf("%2f", i) != -1)
168 return osl_File_E_INVAL;
170 *path = rtl::Uri::decode(
171 url.copy(i), rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
172 // Path must not contain %2F:
173 if (path->indexOf('\0') != -1)
174 return osl_File_E_INVAL;
176 // Handle ~ notation:
177 if (resolveHome && path->getLength() >= 2 && (*path)[1] == '~')
179 sal_Int32 j = path->indexOf('/', 2);
180 if (j == -1)
181 j = path->getLength();
183 if (j == 2)
185 OUString home;
186 if (!osl::Security().getHomeDir(home))
188 SAL_WARN("sal.file", "osl::Security::getHomeDir failed");
189 return osl_File_E_INVAL;
192 i = url.indexOf('/', i + 1);
194 if (i == -1)
195 i = url.getLength();
196 else
197 ++i;
199 //TODO: cheesy way of ensuring home's path ends in slash:
200 if (!home.isEmpty() && home[home.getLength() - 1] != '/')
201 home += "/";
204 home = rtl::Uri::convertRelToAbs(home, url.copy(i));
206 catch (rtl::MalformedUriException & e)
208 SAL_WARN("sal.file", "rtl::MalformedUriException " << e.getMessage());
209 return osl_File_E_INVAL;
211 return getSystemPathFromFileUrl(home, path, false);
213 // FIXME: replace ~user with user's home directory
214 return osl_File_E_INVAL;
216 return osl_File_E_None;
221 oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
223 OUString path;
224 oslFileError e;
227 e = getSystemPathFromFileUrl(
228 OUString::unacquired(&ustrFileURL), &path, true);
230 catch (std::length_error &)
232 e = osl_File_E_RANGE;
235 if (e == osl_File_E_None)
236 rtl_uString_assign(pustrSystemPath, path.pData);
238 return e;
241 oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
243 static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
245 rtl_uString *pTmp = nullptr;
246 sal_Int32 nIndex;
248 if( ustrSystemPath->length == 0 )
249 return osl_File_E_INVAL;
251 /* temporary hack: if already file url, return ustrSystemPath */
253 if( rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) == 0 )
254 return osl_File_E_INVAL;
256 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
257 if( ustrSystemPath->buffer[0] == '~' )
259 /* check if another user is specified */
260 if( ( ustrSystemPath->length == 1 ) ||
261 ( ustrSystemPath->buffer[1] == '/' ) )
263 /* osl_getHomeDir returns file URL */
264 oslSecurity pSecurity = osl_getCurrentSecurity();
265 osl_getHomeDir( pSecurity , &pTmp );
266 osl_freeSecurityHandle( pSecurity );
268 if (!pTmp)
269 return osl_File_E_INVAL;
271 /* remove "file://" prefix */
272 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 );
274 /* replace '~' in original string */
275 rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp );
277 else
279 /* FIXME: replace ~user with users home directory */
280 return osl_File_E_INVAL;
284 /* check if initial string contains repeated '/' characters */
285 nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 );
286 if( nIndex != -1 )
288 sal_Int32 nSrcIndex;
289 sal_Int32 nDeleted = 0;
291 /* if pTmp is not already allocated, copy ustrSystemPath for modification */
292 if( pTmp == nullptr )
293 rtl_uString_newFromString( &pTmp, ustrSystemPath );
295 /* adapt index to pTmp */
296 nIndex += pTmp->length - ustrSystemPath->length;
298 /* replace repeated '/' characters with a single '/' */
299 for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ )
301 if( (pTmp->buffer[nSrcIndex] == '/') && (pTmp->buffer[nIndex] == '/') )
302 nDeleted++;
303 else
304 pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex];
307 /* adjust length member */
308 pTmp->length -= nDeleted;
311 if( pTmp == nullptr )
312 rtl_uString_assign( &pTmp, ustrSystemPath );
314 /* file URLs must be URI encoded */
315 rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL );
317 rtl_uString_release( pTmp );
319 /* absolute urls should start with 'file://' */
320 if( (*pustrFileURL)->buffer[0] == '/' )
322 rtl_uString *pProtocol = nullptr;
324 rtl_uString_newFromAscii( &pProtocol, "file://" );
325 rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL );
326 rtl_uString_release( pProtocol );
329 return osl_File_E_None;
333 * relative URLs are not accepted
335 oslFileError osl_getSystemPathFromFileURL_Ex(
336 rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath)
338 rtl_uString* temp = nullptr;
339 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp);
341 if (osl_error == osl_File_E_None)
343 if (temp->buffer[0] == '/')
345 *pustrSystemPath = temp;
347 else
349 rtl_uString_release(temp);
350 osl_error = osl_File_E_INVAL;
354 return osl_error;
357 namespace
360 /** Helper function, return a pinter to the final '\0'
361 of a string
364 sal_Unicode* ustrtoend(sal_Unicode* pStr)
366 return (pStr + rtl_ustr_getLength(pStr));
369 sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d)
371 sal_Unicode* p = ustrtoend(d);
372 *p++ = chr;
373 *p = 0;
374 return d;
377 bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr)
379 sal_Unicode* p = ustrtoend(pStr);
380 if (p > pStr)
381 p--;
382 return (*p == Chr);
386 Remove the last part of a path, a path that has
387 only a '/' or no '/' at all will be returned
388 unmodified
391 sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
393 /* we may always skip -2 because we
394 may at least stand on a '/' but
395 either there is no other character
396 before this '/' or it's another
397 character than the '/'
399 sal_Unicode* p = ustrtoend(aPath) - 2;
401 /* move back to the next path separator
402 or to the start of the string */
403 while ((p > aPath) && (*p != '/'))
404 p--;
406 if (p >= aPath)
408 if (*p == '/')
410 p++;
411 *p = '\0';
413 else
415 *p = '\0';
419 return aPath;
422 oslFileError _osl_resolvepath(
423 /*inout*/ sal_Unicode* path,
424 /*inout*/ bool* failed)
426 oslFileError ferr = osl_File_E_None;
428 if (!*failed)
430 char unresolved_path[PATH_MAX];
431 if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path)))
432 return oslTranslateFileError(ENAMETOOLONG);
434 char resolved_path[PATH_MAX];
435 if (realpath(unresolved_path, resolved_path))
437 if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
438 return oslTranslateFileError(ENAMETOOLONG);
440 else
442 if (EACCES == errno || ENOTDIR == errno || ENOENT == errno)
443 *failed = true;
444 else
445 ferr = oslTranslateFileError(errno);
449 return ferr;
453 Works even with non existing paths. The resulting path must not exceed
454 PATH_MAX else osl_File_E_NAMETOOLONG is the result
457 oslFileError osl_getAbsoluteFileURL_impl_(const OUString& unresolved_path, OUString& resolved_path)
459 /* the given unresolved path must not exceed PATH_MAX */
460 if (unresolved_path.getLength() >= (PATH_MAX - 2))
461 return oslTranslateFileError(ENAMETOOLONG);
463 sal_Unicode path_resolved_so_far[PATH_MAX];
464 const sal_Unicode* punresolved = unresolved_path.getStr();
465 sal_Unicode* presolvedsf = path_resolved_so_far;
467 /* reserve space for leading '/' and trailing '\0'
468 do not exceed this limit */
469 sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2;
471 /* if realpath fails with error ENOTDIR, EACCES or ENOENT
472 we will not call it again, because _osl_realpath should also
473 work with non existing directories etc. */
474 bool realpath_failed = false;
475 oslFileError ferr;
477 path_resolved_so_far[0] = '\0';
479 while (*punresolved != '\0')
481 /* ignore '/.' , skip one part back when '/..' */
482 if ((*punresolved == '.') && (*presolvedsf == '/'))
484 if (*(punresolved + 1) == '\0')
486 punresolved++;
487 continue;
489 if (*(punresolved + 1) == '/')
491 punresolved += 2;
492 continue;
494 if ((*(punresolved + 1) == '.') && (*(punresolved + 2) == '\0' || (*(punresolved + 2) == '/')))
496 _rmlastpathtoken(path_resolved_so_far);
498 presolvedsf = ustrtoend(path_resolved_so_far) - 1;
500 if (*(punresolved + 2) == '/')
501 punresolved += 3;
502 else
503 punresolved += 2;
505 continue;
508 /* a file or directory name may start with '.' */
509 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
510 return oslTranslateFileError(ENAMETOOLONG);
512 ustrchrcat(*punresolved++, path_resolved_so_far);
514 if (*punresolved == '\0' && !realpath_failed)
516 ferr = _osl_resolvepath(
517 path_resolved_so_far,
518 &realpath_failed);
520 if (ferr != osl_File_E_None)
521 return ferr;
524 else if (*punresolved == '/')
526 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
527 return oslTranslateFileError(ENAMETOOLONG);
529 ustrchrcat(*punresolved++, path_resolved_so_far);
531 if (!realpath_failed)
533 ferr = _osl_resolvepath(
534 path_resolved_so_far,
535 &realpath_failed);
537 if (ferr != osl_File_E_None)
538 return ferr;
540 if (!_islastchr(path_resolved_so_far, '/'))
542 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
543 return oslTranslateFileError(ENAMETOOLONG);
545 ustrchrcat('/', path_resolved_so_far);
549 else // any other character
551 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
552 return oslTranslateFileError(ENAMETOOLONG);
554 ustrchrcat(*punresolved++, path_resolved_so_far);
556 if (*punresolved == '\0' && !realpath_failed)
558 ferr = _osl_resolvepath(
559 path_resolved_so_far,
560 &realpath_failed);
562 if (ferr != osl_File_E_None)
563 return ferr;
568 sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far);
570 OSL_ASSERT(len < PATH_MAX);
572 resolved_path = OUString(path_resolved_so_far, len);
574 return osl_File_E_None;
579 oslFileError osl_getAbsoluteFileURL(
580 rtl_uString* ustrBaseDirURL,
581 rtl_uString* ustrRelativeURL,
582 rtl_uString** pustrAbsoluteURL)
584 /* Work around the below call to getSystemPathFromFileURL rejecting input
585 that starts with "/" (for whatever reason it behaves that way; but
586 changing that would start to break lots of tests at least) */
587 OUString relUrl(ustrRelativeURL);
588 if (relUrl.startsWith("//"))
589 relUrl = "file:" + relUrl;
590 else if (relUrl.startsWith("/"))
591 relUrl = "file://" + relUrl;
593 OUString unresolved_path;
595 FileBase::RC frc = FileBase::getSystemPathFromFileURL(relUrl, unresolved_path);
596 if (frc != FileBase::E_None)
597 return oslFileError(frc);
599 if (systemPathIsRelativePath(unresolved_path))
601 OUString base_path;
602 oslFileError rc = osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData);
603 if (rc != osl_File_E_None)
604 return rc;
606 OUString abs_path;
607 systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path);
609 unresolved_path = abs_path;
612 OUString resolved_path;
613 oslFileError rc = osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
614 if (rc == osl_File_E_None)
616 rc = osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL);
617 OSL_ASSERT(osl_File_E_None == rc);
620 return rc;
623 namespace osl {
624 namespace detail {
627 No separate error code if unicode to text conversion or getenv fails because for the
628 caller there is no difference why a file could not be found in $PATH
630 bool find_in_PATH(const OUString& file_path, OUString& result)
632 bool bfound = false;
633 OUString path("PATH");
634 OUString env_path;
636 if (osl_getEnvironment(path.pData, &env_path.pData) == osl_Process_E_None)
637 bfound = osl::searchPath(file_path, env_path, result);
639 return bfound;
644 namespace
647 No separate error code if unicode to text conversion or getcwd fails because for the
648 caller there is no difference why a file could not be found in CDW
650 bool find_in_CWD(const OUString& file_path, OUString& result)
652 bool bfound = false;
653 OUString cwd_url;
655 if (osl_getProcessWorkingDir(&cwd_url.pData) == osl_Process_E_None)
657 OUString cwd;
658 FileBase::getSystemPathFromFileURL(cwd_url, cwd);
659 bfound = osl::searchPath(file_path, cwd, result);
661 return bfound;
664 bool find_in_searchPath(const OUString& file_path, rtl_uString* search_path, OUString& result)
666 return (search_path && osl::searchPath(file_path, OUString(search_path), result));
671 oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
673 OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
675 FileBase::RC rc;
676 OUString file_path;
678 // try to interpret search path as file url else assume it's a system path list
679 rc = FileBase::getSystemPathFromFileURL(ustrFilePath, file_path);
680 if (rc == FileBase::E_INVAL)
681 file_path = ustrFilePath;
682 else if (rc != FileBase::E_None)
683 return oslFileError(rc);
685 bool bfound = false;
686 OUString result;
688 if (find_in_searchPath(file_path, ustrSearchPath, result) ||
689 osl::detail::find_in_PATH(file_path, result) ||
690 find_in_CWD(file_path, result))
692 OUString resolved;
694 if (osl::realpath(result, resolved))
696 oslFileError osl_error = osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
697 SAL_WARN_IF(osl_File_E_None != osl_error, "sal.file", "osl_getFileURLFromSystemPath failed");
698 bfound = true;
701 return bfound ? osl_File_E_None : osl_File_E_NOENT;
704 oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
706 rtl_uString* ustrSystemPath = nullptr;
707 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
709 if(osl_error != osl_File_E_None)
710 return osl_error;
712 osl_systemPathRemoveSeparator(ustrSystemPath);
714 /* convert unicode path to text */
715 if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
716 osl_error = oslTranslateFileError(errno);
718 rtl_uString_release(ustrSystemPath);
720 return osl_error;
723 namespace
725 class UnicodeToTextConverter_Impl
727 rtl_UnicodeToTextConverter const m_converter;
729 UnicodeToTextConverter_Impl()
730 : m_converter (rtl_createUnicodeToTextConverter (osl_getThreadTextEncoding()))
733 ~UnicodeToTextConverter_Impl()
735 rtl_destroyUnicodeToTextConverter (m_converter);
737 public:
738 static UnicodeToTextConverter_Impl & getInstance()
740 static UnicodeToTextConverter_Impl g_theConverter;
741 return g_theConverter;
744 sal_Size convert(
745 sal_Unicode const * pSrcBuf, sal_Size nSrcChars, sal_Char * pDstBuf, sal_Size nDstBytes,
746 sal_uInt32 nFlags, sal_uInt32 * pInfo, sal_Size * pSrcCvtChars)
748 OSL_ASSERT(m_converter != nullptr);
749 return rtl_convertUnicodeToText (
750 m_converter, nullptr, pSrcBuf, nSrcChars, pDstBuf, nDstBytes, nFlags, pInfo, pSrcCvtChars);
755 int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
757 sal_uInt32 nInfo = 0;
758 sal_Size nSrcChars = 0;
760 sal_Size nDestBytes = UnicodeToTextConverter_Impl::getInstance().convert (
761 uniText, uniTextLen, buffer, bufLen,
762 OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, &nInfo, &nSrcChars);
764 if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
766 errno = EOVERFLOW;
767 return 0;
770 /* ensure trailing '\0' */
771 buffer[nDestBytes] = '\0';
772 return nDestBytes;
775 namespace
777 class TextToUnicodeConverter_Impl
779 rtl_TextToUnicodeConverter const m_converter;
781 TextToUnicodeConverter_Impl()
782 : m_converter (rtl_createTextToUnicodeConverter (osl_getThreadTextEncoding()))
785 ~TextToUnicodeConverter_Impl()
787 rtl_destroyTextToUnicodeConverter (m_converter);
790 public:
791 static TextToUnicodeConverter_Impl & getInstance()
793 static TextToUnicodeConverter_Impl g_theConverter;
794 return g_theConverter;
797 sal_Size convert(
798 sal_Char const * pSrcBuf, sal_Size nSrcBytes, sal_Unicode * pDstBuf, sal_Size nDstChars,
799 sal_uInt32 nFlags, sal_uInt32 * pInfo, sal_Size * pSrcCvtBytes)
801 OSL_ASSERT(m_converter != nullptr);
802 return rtl_convertTextToUnicode (
803 m_converter, nullptr, pSrcBuf, nSrcBytes, pDstBuf, nDstChars, nFlags, pInfo, pSrcCvtBytes);
808 int TextToUnicode(
809 const char* text,
810 size_t text_buffer_size,
811 sal_Unicode* unic_text,
812 sal_Int32 unic_text_buffer_size)
814 sal_uInt32 nInfo = 0;
815 sal_Size nSrcChars = 0;
817 sal_Size nDestBytes = TextToUnicodeConverter_Impl::getInstance().convert(
818 text, text_buffer_size, unic_text, unic_text_buffer_size,
819 OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, &nInfo, &nSrcChars);
821 if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL)
823 errno = EOVERFLOW;
824 return 0;
827 /* ensure trailing '\0' */
828 unic_text[nDestBytes] = '\0';
829 return nDestBytes;
832 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */