2003-03-15 21:20:41 +01:00
|
|
|
/*
|
|
|
|
* PROGRAM: Client/Server Common Code
|
|
|
|
* MODULE: dir_list.cpp
|
|
|
|
* DESCRIPTION: Directory listing config file operation
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* Created by: Alex Peshkov <AlexPeshkov@users.sourceforge.net>
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
2003-03-15 21:20:42 +01:00
|
|
|
#include "firebird.h"
|
2003-03-15 21:20:41 +01:00
|
|
|
#include "../common/config/config.h"
|
|
|
|
#include "../common/config/dir_list.h"
|
|
|
|
#include "../jrd/os/path_utils.h"
|
2003-04-06 17:01:30 +02:00
|
|
|
#include "../jrd/gds_proto.h"
|
2003-03-15 21:20:41 +01:00
|
|
|
|
|
|
|
#define New FB_NEW(*getDefaultMemoryPool())
|
|
|
|
|
|
|
|
ParsedPath::ParsedPath(void) {
|
|
|
|
PathElem = 0;
|
|
|
|
nElem = 0;
|
|
|
|
}
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
ParsedPath::ParsedPath(const Firebird::PathName& path) {
|
2003-03-15 21:20:41 +01:00
|
|
|
PathElem = 0;
|
|
|
|
Parse(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
ParsedPath::~ParsedPath() {
|
|
|
|
delete[] PathElem;
|
|
|
|
}
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
void ParsedPath::Parse(const Firebird::PathName& path) {
|
|
|
|
delete[] PathElem;
|
2003-04-02 17:14:14 +02:00
|
|
|
|
|
|
|
if (path.length() == 1) {
|
|
|
|
nElem = 1;
|
2003-05-30 14:17:47 +02:00
|
|
|
PathElem = New Firebird::PathName[1];
|
2003-04-02 17:14:14 +02:00
|
|
|
PathElem[0] = path;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-03-15 21:20:41 +01:00
|
|
|
nElem = 0;
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName oldpath = path;
|
2003-03-15 21:20:41 +01:00
|
|
|
do {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName newpath, elem;
|
2003-03-15 21:20:41 +01:00
|
|
|
PathUtils::splitLastComponent(newpath, elem, oldpath);
|
|
|
|
oldpath = newpath;
|
|
|
|
nElem++;
|
|
|
|
} while (oldpath.length() > 0);
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
PathElem = New Firebird::PathName[nElem];
|
2003-03-15 21:20:41 +01:00
|
|
|
oldpath = path;
|
2003-03-23 17:50:54 +01:00
|
|
|
for (int i = nElem; i--; ) {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName newpath;
|
2003-03-15 21:20:41 +01:00
|
|
|
PathUtils::splitLastComponent(newpath, PathElem[i], oldpath);
|
|
|
|
oldpath = newpath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-23 17:50:54 +01:00
|
|
|
bool ParsedPath::operator==(const char* path) const {
|
2003-05-30 14:17:47 +02:00
|
|
|
return (Firebird::PathName(*this) == Firebird::PathName(path));
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName ParsedPath::SubPath(int n) const {
|
|
|
|
Firebird::PathName rc = PathElem[0];
|
2003-04-06 17:01:30 +02:00
|
|
|
if (PathUtils::isRelative(rc + PathUtils::dir_sep))
|
2003-03-23 17:50:54 +01:00
|
|
|
rc = PathUtils::dir_sep + rc;
|
|
|
|
for (int i = 1; i < n; i++) {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName newpath;
|
2003-03-15 21:20:41 +01:00
|
|
|
PathUtils::concatPath(newpath, rc, PathElem[i]);
|
|
|
|
rc = newpath;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
ParsedPath::operator Firebird::PathName() const {
|
2003-03-23 17:50:54 +01:00
|
|
|
if (!PathElem)
|
2003-03-15 21:20:41 +01:00
|
|
|
return "";
|
|
|
|
return SubPath(nElem);
|
|
|
|
}
|
|
|
|
|
2003-03-23 17:50:54 +01:00
|
|
|
bool ParsedPath::Contains(const ParsedPath& pPath) const {
|
2003-04-02 17:14:14 +02:00
|
|
|
int nFullElem = nElem;
|
|
|
|
if (nFullElem > 1 && PathElem[nFullElem - 1].length() == 0)
|
|
|
|
nFullElem--;
|
|
|
|
|
|
|
|
if (pPath.nElem < nFullElem) {
|
2003-03-15 21:20:41 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int i;
|
2003-04-02 17:14:14 +02:00
|
|
|
for (i = 0; i < nFullElem; i++) {
|
2003-03-23 17:50:54 +01:00
|
|
|
if (!PathUtils::comparePaths(pPath.PathElem[i], PathElem[i])) {
|
2003-03-15 21:20:41 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2003-04-02 17:14:14 +02:00
|
|
|
for (i = nFullElem + 1; i <= pPath.nElem; i++) {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName x = pPath.SubPath(i);
|
2003-03-15 21:20:41 +01:00
|
|
|
if (PathUtils::isSymLink(x)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
DirectoryList::DirectoryList() {
|
|
|
|
ConfigDirs = 0;
|
|
|
|
nDirs = 0;
|
2003-04-06 17:01:30 +02:00
|
|
|
Mode = NotInitialized;
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DirectoryList::~DirectoryList() {
|
2003-04-06 17:01:30 +02:00
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DirectoryList::KeyWord(
|
|
|
|
const ListMode KeyMode,
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName& Value,
|
|
|
|
Firebird::PathName Key,
|
|
|
|
Firebird::PathName Next
|
2003-04-06 17:01:30 +02:00
|
|
|
) {
|
|
|
|
if (Value.length() < Key.length()) {
|
|
|
|
return false;
|
|
|
|
}
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName KeyValue = Value.substr(0, Key.length());
|
2003-04-06 17:01:30 +02:00
|
|
|
if (KeyValue != Key) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (Next.length() > 0) {
|
|
|
|
if (Value.length() == Key.length()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
KeyValue = Value.substr(Key.length());
|
2003-05-30 14:17:47 +02:00
|
|
|
if (Next.find(KeyValue[0]) == Firebird::PathName::npos) {
|
2003-04-06 17:01:30 +02:00
|
|
|
return false;
|
|
|
|
}
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName::size_type startPos =
|
2003-04-07 17:48:55 +02:00
|
|
|
KeyValue.find_first_not_of(Next);
|
2003-05-30 14:17:47 +02:00
|
|
|
if (startPos == Firebird::PathName::npos) {
|
2003-04-06 17:01:30 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Value = KeyValue.substr(startPos);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (Value.length() > Key.length()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Value.erase();
|
|
|
|
}
|
|
|
|
Mode = KeyMode;
|
|
|
|
return true;
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
|
|
|
|
2003-05-01 14:20:40 +02:00
|
|
|
void DirectoryList::Initialize(bool simple_mode) {
|
|
|
|
if (Mode != NotInitialized)
|
|
|
|
return;
|
|
|
|
|
2003-04-06 17:01:30 +02:00
|
|
|
Clear();
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName val = GetConfigString();
|
2003-05-01 14:20:40 +02:00
|
|
|
|
|
|
|
if (simple_mode) {
|
|
|
|
Mode = SimpleList;
|
2003-04-06 17:01:30 +02:00
|
|
|
}
|
2003-05-01 14:20:40 +02:00
|
|
|
else {
|
|
|
|
if (KeyWord(None, val, "None", "") ||
|
|
|
|
KeyWord(Full, val, "Full", "")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (! KeyWord(Restrict, val, "Restrict", " \t")) {
|
|
|
|
gds__log("DirectoryList: unknown parameter '%s', "
|
|
|
|
"defaulting to None", val.c_str());
|
|
|
|
Mode = None;
|
|
|
|
return;
|
|
|
|
}
|
2003-04-06 17:01:30 +02:00
|
|
|
}
|
|
|
|
|
2003-03-15 21:20:41 +01:00
|
|
|
nDirs = 1;
|
2003-04-02 13:14:29 +02:00
|
|
|
unsigned int i;
|
2003-03-23 17:50:54 +01:00
|
|
|
for (i = 0; i < val.length(); i++) {
|
2003-03-15 21:20:41 +01:00
|
|
|
if (val[i] == ';') {
|
|
|
|
nDirs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ConfigDirs = New ParsedPath[nDirs];
|
2003-04-02 13:14:29 +02:00
|
|
|
unsigned int Last = 0;
|
2003-03-15 21:20:41 +01:00
|
|
|
nDirs = 0;
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName Root = Config::getRootDirectory();
|
2003-03-23 17:50:54 +01:00
|
|
|
for (i = 0; i < val.length(); i++) {
|
2003-03-15 21:20:41 +01:00
|
|
|
if (val[i] == ';') {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName dir = "";
|
2003-03-15 21:20:41 +01:00
|
|
|
if (i > Last) {
|
|
|
|
dir = val.substr(Last, i-Last);
|
2003-05-05 14:26:37 +02:00
|
|
|
Trim(dir);
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
2003-04-06 17:01:30 +02:00
|
|
|
if (PathUtils::isRelative(dir)) {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName newdir;
|
2003-03-15 21:20:41 +01:00
|
|
|
PathUtils::concatPath(newdir, Root, dir);
|
|
|
|
dir = newdir;
|
|
|
|
}
|
|
|
|
ConfigDirs[nDirs++].Parse(dir);
|
|
|
|
Last = i + 1;
|
|
|
|
}
|
|
|
|
}
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName dir = "";
|
2003-03-15 21:20:41 +01:00
|
|
|
if (i > Last) {
|
2003-03-23 17:50:54 +01:00
|
|
|
dir = val.substr(Last, i - Last);
|
2003-05-05 14:26:37 +02:00
|
|
|
Trim(dir);
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
2003-04-06 17:01:30 +02:00
|
|
|
if (PathUtils::isRelative(dir)) {
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName newdir;
|
2003-03-15 21:20:41 +01:00
|
|
|
PathUtils::concatPath(newdir, Root, dir);
|
|
|
|
dir = newdir;
|
|
|
|
}
|
|
|
|
ConfigDirs[nDirs++].Parse(dir);
|
|
|
|
}
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
bool DirectoryList::IsPathInList(const Firebird::PathName& path) {
|
2003-04-12 12:24:39 +02:00
|
|
|
#ifdef BOOT_BUILD
|
|
|
|
return true;
|
|
|
|
#else //BOOT_BUILD
|
2003-05-01 14:20:40 +02:00
|
|
|
Initialize();
|
2003-03-15 21:20:41 +01:00
|
|
|
|
2003-04-06 17:01:30 +02:00
|
|
|
// Handle special cases
|
|
|
|
switch(Mode) {
|
|
|
|
case NotInitialized:
|
|
|
|
case None:
|
|
|
|
return false;
|
|
|
|
case Full:
|
2003-04-03 15:32:28 +02:00
|
|
|
return true;
|
2003-04-06 17:01:30 +02:00
|
|
|
}
|
2003-04-03 15:32:28 +02:00
|
|
|
|
2003-03-15 21:20:41 +01:00
|
|
|
// Disable any up-dir(..) references - in case our path_utils
|
|
|
|
// and OS handle paths in slightly different ways,
|
|
|
|
// this is "wonderful" potential hole for hacks
|
|
|
|
// Example of IIS attack attempt:
|
|
|
|
// "GET /scripts/..%252f../winnt/system32/cmd.exe?/c+dir HTTP/1.0"
|
2003-04-12 12:24:39 +02:00
|
|
|
// (live from apache access.log :)
|
2003-05-30 14:17:47 +02:00
|
|
|
if (path.find(PathUtils::up_dir_link) != Firebird::PathName::npos)
|
2003-03-15 21:20:41 +01:00
|
|
|
return false;
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName varpath = path;
|
2003-03-15 21:20:41 +01:00
|
|
|
if (PathUtils::isRelative(path)) {
|
|
|
|
PathUtils::concatPath(varpath,
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName(Config::getRootDirectory()), path);
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ParsedPath pPath = path;
|
|
|
|
bool rc = 0;
|
2003-03-23 17:50:54 +01:00
|
|
|
for (int i = 0; i < nDirs; i++) {
|
2003-03-15 21:20:41 +01:00
|
|
|
if (ConfigDirs[i].Contains(pPath)) {
|
|
|
|
rc = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rc;
|
2003-04-12 12:24:39 +02:00
|
|
|
#endif //BOOT_BUILD
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
2003-03-23 17:50:54 +01:00
|
|
|
|
|
|
|
void DirectoryList::ExpandFileName (
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName & Path,
|
|
|
|
const Firebird::PathName & Name,
|
2003-03-23 17:50:54 +01:00
|
|
|
int Access
|
|
|
|
) {
|
2003-04-12 12:24:39 +02:00
|
|
|
if (Mode == NotInitialized)
|
2003-03-23 17:50:54 +01:00
|
|
|
Initialize();
|
|
|
|
for (int i = 0; i < nDirs; i++) {
|
|
|
|
PathUtils::concatPath(Path, ConfigDirs[i], Name);
|
|
|
|
if (PathUtils::canAccess(Path, Access)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Path = Name;
|
|
|
|
}
|
2003-05-01 14:20:40 +02:00
|
|
|
|
|
|
|
TempDirectoryList::TempDirectoryList() : items(0)
|
|
|
|
{
|
|
|
|
Initialize(true);
|
|
|
|
|
|
|
|
// Get directory list
|
|
|
|
const ParsedPath* dir_list = DirList();
|
|
|
|
|
|
|
|
// Iterate through directories to parse them
|
|
|
|
// and fill the "items" vector
|
|
|
|
for (int i = 0; i < DirCount(); i++) {
|
|
|
|
Item item;
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName dir = dir_list[i];
|
2003-05-01 14:20:40 +02:00
|
|
|
int pos = dir.rfind(" ");
|
2003-05-30 14:17:47 +02:00
|
|
|
long size = atol(dir.substr(pos + 1, Firebird::PathName::npos).c_str());
|
|
|
|
if (pos != Firebird::PathName::npos && !size) {
|
|
|
|
pos = Firebird::PathName::npos;
|
2003-05-01 14:20:40 +02:00
|
|
|
}
|
|
|
|
if (size <= 0) {
|
|
|
|
size = ALLROOM;
|
|
|
|
}
|
|
|
|
item.dir = dir.substr(0, pos);
|
|
|
|
item.size = size;
|
|
|
|
items.push_back(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-30 14:17:47 +02:00
|
|
|
const Firebird::PathName TempDirectoryList::GetConfigString() const
|
2003-05-01 14:20:40 +02:00
|
|
|
{
|
|
|
|
const char* value;
|
|
|
|
if (!(value = Config::getTempDirectories()) &&
|
|
|
|
// Temporary directory configuration has not been defined.
|
|
|
|
// Let's make default configuration.
|
|
|
|
!(value = getenv("INTERBASE_TMP")) && // shouldn't it be FIREBIRD_TMP???
|
|
|
|
!(value = getenv("TMP")) &&
|
|
|
|
!(value = getenv("TEMP")))
|
|
|
|
{
|
|
|
|
value = WORKDIR;
|
|
|
|
}
|
2003-05-30 14:17:47 +02:00
|
|
|
return Firebird::PathName(value);
|
2003-05-01 14:20:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t TempDirectoryList::Count() const
|
|
|
|
{
|
|
|
|
return items.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
const TempDirectoryList::Item& TempDirectoryList::operator[](size_t i) const
|
|
|
|
{
|
|
|
|
return items[i];
|
|
|
|
}
|