271 lines
6.4 KiB
C++
271 lines
6.4 KiB
C++
//----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 2004 Intel Corporation
|
|
//
|
|
// File: Options.cpp
|
|
//
|
|
// contents: This file contains the implementation of a generic class for command line options
|
|
// parsing.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "Options.h"
|
|
#include "CommonDefinitions.h"
|
|
|
|
#include <string.h>
|
|
#include <set>
|
|
using namespace std;
|
|
|
|
bool Options::StrLess::operator()(const char* left, const char* right) const
|
|
{
|
|
return (_stricmp(left, right) < 0);
|
|
}
|
|
|
|
Options::Format::Format(const Options::FormatNode rawFormat[], int rawFormatSize)
|
|
{
|
|
for (int i=0; i<rawFormatSize; i++)
|
|
AddOption(rawFormat[i].option, rawFormat[i].bHasParam);
|
|
}
|
|
|
|
Options::Format::Format()
|
|
{
|
|
}
|
|
|
|
void Options::Format::AddOption(const char* option, bool bHasParam)
|
|
{
|
|
m_formatMap[option] = bHasParam;
|
|
}
|
|
|
|
bool Options::Format::OptionExists(const char *option) const
|
|
{
|
|
return (m_formatMap.find(option) != m_formatMap.end());
|
|
}
|
|
|
|
bool Options::Format::OptionHasParam(const char* option) const
|
|
{
|
|
FormatMap::const_iterator it = m_formatMap.find(option);
|
|
if (it == m_formatMap.end())
|
|
return false; //Option not found - so it doesn't have a parameter.
|
|
return it->second;
|
|
}
|
|
|
|
bool Options::OptionExists(const char* option) const
|
|
{
|
|
return m_optionsMap.find(option) != m_optionsMap.end();
|
|
}
|
|
|
|
/*
|
|
This parsing function goes over the command line, looking for words that begin with '-'.
|
|
When '-' is found, we check if this is a valid option. If it is, and it has a parameter, the
|
|
next word in the command line is assumed to be its value.
|
|
*/
|
|
bool Options::Parse(int argc, const char* argv[],
|
|
const Format &format)
|
|
{
|
|
const char* optionName = NULL;
|
|
const char* optionVal = NULL;
|
|
|
|
if ((argv == NULL) || (argc < 0))
|
|
return false;
|
|
|
|
//We start from the second parameter, since the first is the program name.
|
|
for (int i=1; i<argc; i++)
|
|
{
|
|
if (argv[i][0] == '-')
|
|
{
|
|
optionName = argv[i] + 1;
|
|
if (OptionExists(optionName))
|
|
{
|
|
/*The option was already specified in this command line -
|
|
this is considered as an error.*/
|
|
return false;
|
|
}
|
|
|
|
if (!format.OptionExists(optionName))
|
|
{
|
|
/*This option was not specified in the format.*/
|
|
return false;
|
|
}
|
|
|
|
if (format.OptionHasParam(optionName))
|
|
{
|
|
//If this option has a parameter, read it and skip it.
|
|
if (++i >= argc)
|
|
return false; //error - this option should have a parameter.
|
|
//If this option is user-name or password check it's max limit allowed.
|
|
//if(((strcmp(optionName,USER+1)==0) && (strlen(argv[i]) > USER_MAX_LEN)) || ((strcmp(optionName,PASS+1)==0) && (strlen(argv[i]) > PASS_MAX_LEN)))
|
|
if(((strcmp(optionName,USER+1)==0) && (strnlen_s(argv[i], USER_MAX_LEN+1) > USER_MAX_LEN)) || ((strcmp(optionName,PASS+1)==0) && (strnlen_s(argv[i], PASS_MAX_LEN+1) > PASS_MAX_LEN)))
|
|
|
|
//If this option is user-name check it valid
|
|
if (strcmp(optionName, USER + 1) == 0)
|
|
{
|
|
if (!validateUserName(strnlen_s(argv[i], USER_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (strcmp(optionName, PASS + 1) == 0)
|
|
{
|
|
if (!validatePassword(strnlen_s(argv[i], PASS_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
//TODO check if user enter certificate or common-name
|
|
if (strcmp(optionName, COMMON_NAME + 1) == 0)
|
|
{
|
|
if (!validateCertificate(strnlen_s(argv[i], CERT_CN_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (strcmp(optionName, HOST + 1) == 0)
|
|
{
|
|
if (!validateIP(argv[i]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (strcmp(optionName, PROXY + 1) == 0)
|
|
{
|
|
if (!validateIP(argv[i]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (strcmp(optionName, PROXY_USER_NAME + 1) == 0)
|
|
{
|
|
if (!validateUserName(strnlen_s(argv[i], USER_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (strcmp(optionName, PROXY_PASSWORD + 1) == 0)
|
|
{
|
|
if (!validatePassword(strnlen_s(argv[i], PASS_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (strcmp(optionName, PROXY_SOCKS + 1) == 0)
|
|
{
|
|
if (!validateIP(argv[i]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (strcmp(optionName, PROXY_SOCKS_USER_NAME + 1) == 0)
|
|
{
|
|
if (!validateUserName(strnlen_s(argv[i], USER_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (strcmp(optionName, PROXY_SOCKS_PASSWORD + 1) == 0)
|
|
{
|
|
if (!validatePassword(strnlen_s(argv[i], PASS_MAX_LEN +1)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
optionVal = argv[i];
|
|
}
|
|
else
|
|
{
|
|
optionVal = "";
|
|
}
|
|
m_optionsMap[optionName] = optionVal;
|
|
}
|
|
else
|
|
{
|
|
//No option can be without '-'
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_parsed = true;
|
|
return true;
|
|
}
|
|
|
|
bool Options::validateUserName( int len)
|
|
{
|
|
if (len > USER_MAX_LEN)
|
|
{
|
|
printf("Invalid parameter: user-name is too long\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
//we don't check an empty value for kerberos conection
|
|
}
|
|
bool Options::validatePassword(int len)
|
|
{
|
|
if (len > PASS_MAX_LEN)
|
|
{
|
|
printf("Invalid parameter: password is too long\n");
|
|
return false;
|
|
}
|
|
if (len < PASS_MIN_LEN && len != 0)
|
|
{
|
|
printf("Invalid parameter: password is too short\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
bool Options::validateCertificate(int len)
|
|
{
|
|
if (len > CERT_CN_MAX_LEN)// In the common name field of the CN of a X509 certificate, , the limit is up to 64 characters
|
|
{
|
|
printf("Invalid parameter: certificate is too long\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
bool Options::validateIP(const char* ip)
|
|
{
|
|
unsigned long addr = inet_addr(ip);
|
|
if (INADDR_NONE != addr && INADDR_ANY != addr) {
|
|
//if it is valid dotted-decimal address
|
|
//convert back to string will prevent unwanted duplicates
|
|
struct in_addr inaddr;
|
|
inaddr.s_addr = addr;
|
|
ip = inet_ntoa(inaddr);
|
|
if (!ip) {
|
|
printf("Invalid IP address");
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Options::Parse(int argc, const char* argv[],
|
|
const FormatNode rawFormat[], int rawFormatSize)
|
|
{
|
|
return Parse(argc, argv, Format(rawFormat, rawFormatSize));
|
|
}
|
|
|
|
Options::Options(int argc, const char* argv[],
|
|
const Format &format)
|
|
{
|
|
Parse(argc, argv, format);
|
|
}
|
|
|
|
Options::Options(int argc, const char* argv[],
|
|
const FormatNode rawFormat[], int rawFormatSize)
|
|
{
|
|
Parse(argc, argv, rawFormat, rawFormatSize);
|
|
}
|
|
|
|
Options::Options()
|
|
{
|
|
m_parsed = false;
|
|
}
|
|
|
|
const char* Options::GetOption(const char* option) const
|
|
{
|
|
OptionsMap::const_iterator it = m_optionsMap.find(option);
|
|
return (it == m_optionsMap.end()) ? NULL : it->second;
|
|
}
|