Coverage Report

Created: 2025-12-10 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poco/Foundation/src/URIStreamOpener.cpp
Line
Count
Source
1
//
2
// URIStreamOpener.cpp
3
//
4
// Library: Foundation
5
// Package: URI
6
// Module:  URIStreamOpener
7
//
8
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9
// and Contributors.
10
//
11
// SPDX-License-Identifier: BSL-1.0
12
//
13
14
15
#include "Poco/URIStreamOpener.h"
16
#include "Poco/URIStreamFactory.h"
17
#include "Poco/FileStreamFactory.h"
18
#include "Poco/URI.h"
19
#include "Poco/Path.h"
20
#include "Poco/Exception.h"
21
22
23
namespace Poco {
24
25
26
URIStreamOpener::URIStreamOpener()
27
1
{
28
1
  registerStreamFactory("file", new FileStreamFactory);
29
1
}
30
31
32
URIStreamOpener::~URIStreamOpener()
33
1
{
34
1
  for (auto& p: _map) delete p.second;
35
1
}
36
37
38
std::istream* URIStreamOpener::open(const URI& uri) const
39
0
{
40
0
  FastMutex::ScopedLock lock(_mutex);
41
42
0
  std::string scheme;
43
0
  if (uri.isRelative())
44
0
    scheme = "file";
45
0
  else
46
0
    scheme = uri.getScheme();
47
0
  return openURI(scheme, uri);
48
0
}
49
50
51
std::istream* URIStreamOpener::open(const std::string& pathOrURI) const
52
71.4k
{
53
71.4k
  FastMutex::ScopedLock lock(_mutex);
54
55
71.4k
  try
56
71.4k
  {
57
71.4k
    URI uri(pathOrURI);
58
71.4k
    const std::string& scheme(uri.getScheme());
59
71.4k
    FactoryMap::const_iterator it = _map.find(scheme);
60
71.4k
    if (it != _map.end())
61
12.2k
    {
62
12.2k
      return openURI(scheme, uri);
63
12.2k
    }
64
59.2k
    else if (scheme.length() <= 1) // could be Windows path
65
52.4k
    {
66
52.4k
      Path path;
67
52.4k
      if (path.tryParse(pathOrURI, Path::PATH_GUESS))
68
52.1k
      {
69
52.1k
        return openFile(path);
70
52.1k
      }
71
52.4k
    }
72
7.12k
    throw UnknownURISchemeException(pathOrURI);
73
71.4k
  }
74
71.4k
  catch (URISyntaxException&)
75
71.4k
  {
76
6.03k
    Path path;
77
6.03k
    if (path.tryParse(pathOrURI, Path::PATH_GUESS))
78
5.98k
      return openFile(path);
79
55
    else
80
55
      throw;
81
6.03k
  }
82
71.4k
}
83
84
85
std::istream* URIStreamOpener::open(const std::string& basePathOrURI, const std::string& pathOrURI) const
86
0
{
87
0
  FastMutex::ScopedLock lock(_mutex);
88
89
0
  try
90
0
  {
91
0
    URI uri(basePathOrURI);
92
0
    std::string scheme(uri.getScheme());
93
0
    FactoryMap::const_iterator it = _map.find(scheme);
94
0
    if (it != _map.end())
95
0
    {
96
0
      uri.resolve(pathOrURI);
97
0
      scheme = uri.getScheme();
98
0
      return openURI(scheme, uri);
99
0
    }
100
0
    else if (scheme.length() <= 1) // could be Windows path
101
0
    {
102
0
      Path base;
103
0
      Path path;
104
0
      if (base.tryParse(basePathOrURI, Path::PATH_GUESS) && path.tryParse(pathOrURI, Path::PATH_GUESS))
105
0
      {
106
0
        base.resolve(path);
107
0
        return openFile(base);
108
0
      }
109
0
    }
110
0
    throw UnknownURISchemeException(basePathOrURI);
111
0
  }
112
0
  catch (URISyntaxException&)
113
0
  {
114
0
    Path base;
115
0
    Path path;
116
0
    if (base.tryParse(basePathOrURI, Path::PATH_GUESS) && path.tryParse(pathOrURI, Path::PATH_GUESS))
117
0
    {
118
0
      base.resolve(path);
119
0
      return openFile(base);
120
0
    }
121
0
    else throw;
122
0
  }
123
0
}
124
125
126
void URIStreamOpener::registerStreamFactory(const std::string& scheme, URIStreamFactory* pFactory)
127
1
{
128
1
  poco_check_ptr (pFactory);
129
130
1
  FastMutex::ScopedLock lock(_mutex);
131
1
  if (_map.find(scheme) == _map.end())
132
1
  {
133
1
    _map[scheme] = pFactory;
134
1
  }
135
0
  else throw ExistsException("An URIStreamFactory for the given scheme has already been registered", scheme);
136
1
}
137
138
139
void URIStreamOpener::unregisterStreamFactory(const std::string& scheme)
140
0
{
141
0
  FastMutex::ScopedLock lock(_mutex);
142
143
0
  FactoryMap::iterator it = _map.find(scheme);
144
0
  if (it != _map.end())
145
0
  {
146
0
    URIStreamFactory* pFactory = it->second;
147
0
    _map.erase(it);
148
0
    delete pFactory;
149
0
  }
150
0
  else throw NotFoundException("No URIStreamFactory has been registered for the given scheme", scheme);
151
0
}
152
153
154
bool URIStreamOpener::supportsScheme(const std::string& scheme)
155
0
{
156
0
  FastMutex::ScopedLock lock(_mutex);
157
0
  return _map.find(scheme) != _map.end();
158
0
}
159
160
161
URIStreamOpener& URIStreamOpener::defaultOpener()
162
74.2k
{
163
74.2k
  static URIStreamOpener so;
164
74.2k
  return so;
165
74.2k
}
166
167
168
std::istream* URIStreamOpener::openFile(const Path& path) const
169
58.0k
{
170
58.0k
  FileStreamFactory factory;
171
58.0k
  return factory.open(path);
172
58.0k
}
173
174
175
std::istream* URIStreamOpener::openURI(const std::string& scheme, const URI& uri) const
176
12.2k
{
177
12.2k
  std::string actualScheme(scheme);
178
12.2k
  URI actualURI(uri);
179
12.2k
  int redirects = 0;
180
181
12.2k
  while (redirects < MAX_REDIRECTS)
182
12.2k
  {
183
12.2k
    try
184
12.2k
    {
185
12.2k
      FactoryMap::const_iterator it = _map.find(actualScheme);
186
12.2k
      if (it != _map.end())
187
12.2k
        return it->second->open(actualURI);
188
0
      else if (redirects > 0)
189
0
        throw UnknownURISchemeException(actualURI.toString() + std::string("; redirected from ") + uri.toString());
190
0
      else
191
0
        throw UnknownURISchemeException(actualURI.toString());
192
12.2k
    }
193
12.2k
    catch (URIRedirection& redir)
194
12.2k
    {
195
0
      actualURI = redir.uri();
196
0
      actualScheme = actualURI.getScheme();
197
0
      ++redirects;
198
0
    }
199
12.2k
  }
200
0
  throw TooManyURIRedirectsException(uri.toString());
201
12.2k
}
202
203
204
} // namespace Poco