Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/connectivity/source/commontools/CommonTools.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <config_java.h>
21
22
#include <connectivity/CommonTools.hxx>
23
#include <connectivity/dbtools.hxx>
24
#include <com/sun/star/java/JavaVirtualMachine.hpp>
25
#if HAVE_FEATURE_JAVA
26
#include <jvmaccess/virtualmachine.hxx>
27
#endif
28
#include <osl/diagnose.h>
29
#include <rtl/character.hxx>
30
#include <rtl/process.h>
31
#include <comphelper/diagnose_ex.hxx>
32
33
static sal_Unicode rtl_ascii_toUpperCase( sal_Unicode ch )
34
39.1k
{
35
39.1k
    return ch >= 0x0061 && ch <= 0x007a ? ch + 0x20 : ch;
36
39.1k
}
37
38
namespace connectivity
39
{
40
    using namespace ::com::sun::star::uno;
41
    using namespace ::com::sun::star::java;
42
    using namespace dbtools;
43
44
    const sal_Unicode CHAR_PLACE = '_';
45
    const sal_Unicode CHAR_WILD  = '%';
46
47
    bool match(const sal_Unicode* pWild, const sal_Unicode* pStr, const sal_Unicode cEscape)
48
376k
    {
49
376k
        int    pos=0;
50
376k
        int    flag=0;
51
52
396k
        while ( *pWild || flag )
53
376k
        {
54
376k
            switch (*pWild)
55
376k
            {
56
0
                case CHAR_PLACE:
57
0
                    if ( *pStr == 0 )
58
0
                        return false;
59
0
                    break;
60
19.5k
                default:
61
19.5k
                    if (*pWild && (*pWild == cEscape) && ((*(pWild+1)== CHAR_PLACE) || (*(pWild+1) == CHAR_WILD)) )
62
0
                        pWild++;
63
19.5k
                    if ( rtl_ascii_toUpperCase(*pWild) != rtl_ascii_toUpperCase(*pStr) )
64
0
                        if ( !pos )
65
0
                            return false;
66
0
                        else
67
0
                            pWild += pos;
68
19.5k
                    else
69
19.5k
                        break;
70
                    // WARNING/TODO: in certain circumstances it will run into
71
                    // the next 'case'!
72
0
                    [[fallthrough]];
73
357k
                case CHAR_WILD:
74
714k
                    while ( *pWild == CHAR_WILD )
75
357k
                        pWild++;
76
357k
                    if ( *pWild == 0 )
77
357k
                        return true;
78
0
                    flag = 1;
79
0
                    pos  = 0;
80
0
                    if ( *pStr == 0 )
81
0
                        return ( *pWild == 0 );
82
0
                    while ( *pStr && *pStr != *pWild )
83
0
                    {
84
0
                        if ( *pWild == CHAR_PLACE ) {
85
0
                            pWild++;
86
0
                            while ( *pWild == CHAR_WILD )
87
0
                                pWild++;
88
0
                        }
89
0
                        pStr++;
90
0
                        if ( *pStr == 0 )
91
0
                            return ( *pWild == 0 );
92
0
                    }
93
0
                    break;
94
376k
            }
95
19.5k
            if ( *pWild != 0 )
96
19.5k
                pWild++;
97
19.5k
            if ( *pStr != 0 )
98
19.5k
                pStr++;
99
0
            else
100
0
                flag = 0;
101
19.5k
            if ( flag )
102
0
                pos--;
103
19.5k
        }
104
19.5k
        return ( *pStr == 0 ) && ( *pWild == 0 );
105
376k
    }
106
107
#if HAVE_FEATURE_JAVA
108
    ::rtl::Reference< jvmaccess::VirtualMachine > getJavaVM(const Reference<XComponentContext >& _rxContext)
109
    {
110
        ::rtl::Reference< jvmaccess::VirtualMachine > aRet;
111
        OSL_ENSURE(_rxContext.is(),"No XMultiServiceFactory a.v.!");
112
        if(!_rxContext.is())
113
            return aRet;
114
115
        try
116
        {
117
            Reference< XJavaVM > xVM = JavaVirtualMachine::create(_rxContext);
118
119
            Sequence<sal_Int8> processID(17); // 16 + 1
120
            auto pprocessID = processID.getArray();
121
            rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8*>(pprocessID) );
122
            pprocessID[16] = 0; // RETURN_VIRTUALMACHINE
123
124
            Any uaJVM = xVM->getJavaVM( processID );
125
            sal_Int64 nTemp;
126
            if (!(uaJVM >>= nTemp)) {
127
                throw Exception(u"cannot get result for getJavaVM"_ustr, nullptr); // -5
128
            }
129
            aRet = reinterpret_cast<jvmaccess::VirtualMachine *>(
130
                static_cast<sal_IntPtr>(nTemp));
131
        }
132
        catch (Exception&)
133
        {
134
            TOOLS_WARN_EXCEPTION("connectivity.commontools", "getJavaVM failed:");
135
        }
136
137
        return aRet;
138
    }
139
140
    bool existsJavaClassByName( const ::rtl::Reference< jvmaccess::VirtualMachine >& _pJVM,std::u16string_view _sClassName )
141
    {
142
        bool bRet = false;
143
        if ( _pJVM.is() )
144
        {
145
            jvmaccess::VirtualMachine::AttachGuard aGuard(_pJVM);
146
            JNIEnv* pEnv = aGuard.getEnvironment();
147
            if( pEnv )
148
            {
149
                OString sClassName = OUStringToOString(_sClassName, RTL_TEXTENCODING_ASCII_US);
150
                sClassName = sClassName.replace('.','/');
151
                jobject out = pEnv->FindClass(sClassName.getStr());
152
                bRet = out != nullptr;
153
                pEnv->DeleteLocalRef( out );
154
            }
155
        }
156
        return bRet;
157
    }
158
#endif
159
}
160
161
namespace dbtools
162
{
163
164
static bool isCharOk(sal_Unicode c, std::u16string_view _rSpecials)
165
0
{
166
167
0
    return ( ((c >= 97) && (c <= 122)) || ((c >= 65) && (c <=  90)) || ((c >= 48) && (c <=  57)) ||
168
0
          c == '_' || _rSpecials.find(c) != std::u16string_view::npos);
169
0
}
170
171
172
bool isValidSQLName(const OUString& rName, std::u16string_view _rSpecials)
173
0
{
174
    // Test for correct naming (in SQL sense)
175
    // This is important for table names for example
176
0
    const sal_Unicode* pStr = rName.getStr();
177
0
    if (*pStr > 127 || rtl::isAsciiDigit(*pStr))
178
0
        return false;
179
180
0
    for (; *pStr; ++pStr )
181
0
        if(!isCharOk(*pStr,_rSpecials))
182
0
            return false;
183
184
0
    if  (   !rName.isEmpty()
185
0
        &&  (   (rName.toChar() == '_')
186
0
            ||  (   (rName.toChar() >= '0')
187
0
                &&  (rName.toChar() <= '9')
188
0
                )
189
0
            )
190
0
        )
191
0
        return false;
192
    // the SQL-Standard requires the first character to be an alphabetic character, which
193
    // isn't easy to decide in UniCode...
194
    // So we just prohibit the characters which already lead to problems...
195
    // 11.04.00 - 74902 - FS
196
197
0
    return true;
198
0
}
199
200
// Creates a new name if necessary
201
OUString convertName2SQLName(const OUString& rName, std::u16string_view _rSpecials)
202
0
{
203
0
    if(isValidSQLName(rName,_rSpecials))
204
0
        return rName;
205
206
0
    const sal_Unicode* pStr = rName.getStr();
207
    // if not valid
208
0
    if (*pStr >= 128 || rtl::isAsciiDigit(*pStr))
209
0
        return OUString();
210
211
0
    OUStringBuffer aNewName(rName);
212
0
    sal_Int32 nLength = rName.getLength();
213
0
    for (sal_Int32 i=0; i < nLength; ++i)
214
0
        if(!isCharOk(aNewName[i],_rSpecials))
215
0
            aNewName[i] = '_';
216
217
0
    return aNewName.makeStringAndClear();
218
0
}
219
220
OUString quoteName(std::u16string_view _rQuote, const OUString& _rName)
221
19.0k
{
222
19.0k
    OUString sName = _rName;
223
19.0k
    if( !_rQuote.empty() && _rQuote[0] != ' ')
224
19.0k
        sName = _rQuote + _rName + _rQuote;
225
19.0k
    return sName;
226
19.0k
}
227
228
229
}
230
231
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */