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;
}