I am using an .ini file to store some values and retrieve values from it using the iniparser.
When I give (hardcode) the query and retrive the value through the command line, I am able to retrive the ini file and do some operation.
But when I pass the query through http, then I am getting an error (file not found), i.e., the ini file couldn't be loaded.
Command line :
int main(void)
{
printf("Content-type: text/html; charset=utf-8\n\n");
char* data = "/cgi-bin/set.cgi?pname=x&value=700&url=http://IP/home.html";
//perform some operation
}
Through http:
.html
function SetValue(id)
{
var val;
var URL = window.location.href;
if(id =="set")
{
document.location = "/cgi-bin/set.cgi?pname="+rwparams+"&value="+val+"&url="+URL;
}
}
.c
int * Value(char* pname)
{
dictionary * ini ;
char *key1 = NULL;
char *key2 =NULL;
int i =0;
int val;
ini = iniparser_load("file.ini");
if(ini != NULL)
{
//key for fetching the value
key1 = (char*)malloc(sizeof(char)*50);
if(key1 != NULL)
{
strcpy(key1,"ValueList:");
key2 = (char*)malloc(sizeof(char)*50);
if(key2 != NULL)
{
strcpy(key2,pname);
strcat(key1,key2);
val = iniparser_getint(ini, key1, -1);
if(-1 == val || 0 > val)
{
return 0;
}
}
else
{
//error
free(key1);
return;
}
}
else
{
printf("ERROR : Memory Allocation Failure ");
return;
}
}
else
{
printf("ERROR : .ini File Missing");
return;
}
iniparser_freedict(ini);
free(key1);
free(key2);
return (int *)val;
}
void get_Value(char* pname,char* value)
{
int result =0;
result = Value(pname);
printf("Result : %d",result);
}
int main(void)
{
printf("Content-type: text/html; charset=utf-8\n\n");
char* data = getenv("QUERY_STRING");
//char* data = "/cgi-bin/set.cgi?pname=x&value=700&url=http://10.50.25.40/home.html";
//Parse to get the values seperately as parameter name, parameter value, url
//Calling get_Value method to set the value
get_Value(final_para,final_val);
}
*
file.ini
*
[ValueList]
x = 100;
y = 70;
When the request is sent through html page, I am always getting .ini file missing. If directly the request is sent from C file them it works fine.
How to resolve this?
Perhaps you have a problem with encoding of the URL parameters? You can't just pass any arbitrary string through a URL - there are some characters that must be encoded. Read this page about URL encoding.
Showing the value of the data string in your C program could be of great help with solving your problem.
Update:
There could be a difference as to where your program executes when called by the web server or directly by you. Are you sure it's being executed with the same "current directory". Chances are it's different, and thus when you attempt to open the ini file you fail. Try to print out the current directory (i.e. using the getcwd function) and compare both cases.
Related
I'm new to HTTP and MFC. I suppose to upload a binary file to a given URL, by sending PUT request. I'm sure the requesting URL and the header are well formed and the file works well, because I tried them by Postman then get a SUCCESS returned.
But when I try to do this by the following MFC code, it always returns a 403 error. Please help me.
bool UploadFile(LPCTSTR strUrl, LPCTSTR filenameFullpath, CString header)
{
BOOL bResult = FALSE;
DWORD dwType = 0;
CString strServer;
CString strObject;
INTERNET_PORT wPort = 0;
DWORD dwFileLength = 0;
BYTE * pFileBuff = NULL;
CHttpConnection * pHC = NULL;
CHttpFile * pHF = NULL;
CInternetSession cis;
bResult = AfxParseURL(strUrl, dwType, strServer, strObject, wPort);
if (!bResult)
return FALSE;
CFile file;
try
{
// Read the file
if (!file.Open(filenameFullpath, CFile::shareDenyNone | CFile::modeRead))
return FALSE;
dwFileLength = file.GetLength();
if (dwFileLength <= 0)
return FALSE;
pFileBuff = new BYTE[dwFileLength];
memset(pFileBuff, 0, sizeof(BYTE) * dwFileLength);
file.Read(pFileBuff, dwFileLength);
// Set up internet connection
const int nTimeOut = 5000;
cis.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut);
cis.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 2); // Retry once if failed
pHC = cis.GetHttpConnection(strServer, dwType == AFX_INET_SERVICE_HTTP ? NORMAL_CONNECT : SECURE_CONNECT, wPort); // Get a HTTP connection
pHF = pHC->OpenRequest(CHttpConnection::HTTP_VERB_PUT, strObject);//strObject
pHF->AddRequestHeaders(header , HTTP_ADDREQ_FLAG_ADD_IF_NEW);
// I set the header separately instead of passing it as the first parameter of the next call.
// If I don't do so, another error occurs
if (!pHF->SendRequest(NULL, 0, pFileBuff, dwFileLength))
{
delete[]pFileBuff;
pFileBuff = NULL;
pHF->Close();
pHC->Close();
cis.Close();
return FALSE;
}
DWORD dwStateCode = 0;
pHF->QueryInfoStatusCode(dwStateCode);
if (dwStateCode == HTTP_STATUS_OK)
bResult = TRUE;
}
catch (CInternetException * pEx)
{
char sz[256] = "";
pEx->GetErrorMessage(sz, 25);
CString str;
str.Format("InternetException occur!\r\n%s", sz);
AfxMessageBox(str);
}
delete[]pFileBuff;
pFileBuff = NULL;
file.Close();
pHF->Close();
pHC->Close();
cis.Close();
return bResult;
}
And the calling of this function is just something like this:
CHttpClient hc;
hc.UploadFile(csUrl, "E:\\blah blah blah\\blah.tma", csUploadHeader);
while csUrl and csUploadHeader are well formed CString;
I got it! I should give pHF the header items (the key-value pairs) one by one, by calling the AddRequestHeaders() method several times, instead of wrapping and passing them together to pHF.
Then the following codes works very well:
CString sHeader1, sHeader2, sHeader3;
sHeader1.Format(_T("%s : %s"), sKey1, sValue1); // sKey_, sValue_ are strings
sHeader2.Format(_T("%s : %s"), sKey2, sValue2);
sHeader3.Format(_T("%s : %s"), sKey3, sValue3);
pHF->AddRequestHeaders(sHeader1, HTTP_ADDREQ_FLAG_ADD_IF_NEW); // Keep the second paeramter as these
pHF->AddRequestHeaders(sHeader2, HTTP_ADDREQ_FLAG_COALESCE);
pHF->AddRequestHeaders(sHeader3, HTTP_ADDREQ_FLAG_COALESCE);
And a very important notification: the string we pass to AddRequestHeaders() should not have the quotation("") around either the key or the value. In other words, string like "MyKey":"MyValue" have to be modified as MyKey:MyValue before giving to AddRequestHeaders();
I'm trying to get a blob of a repository with libgit2:
#include <git2.h>
#include <stdio.h>
int main() {
git_libgit2_init();
git_repository *repo = NULL;
int error = git_repository_open(&repo, "/home/martin/Dokumente/TestRepository");
if (error < 0) {
const git_error *e = git_error_last();
printf("Error %d/%d: %s\n", error, e->klass, e->message);
exit(error);
}
git_diff *diff = NULL;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
opts.flags |= GIT_DIFF_IGNORE_WHITESPACE;
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
error = git_diff_index_to_workdir(&diff, repo, NULL, &opts);
if (error < 0) {
const git_error *e = git_error_last();
printf("Error %d/%d: %s\n", error, e->klass, e->message);
exit(error);
}
git_patch* patch = nullptr;
git_patch_from_diff(&patch, diff, 0);
bool oldFile = false;
const git_diff_delta *dd = git_patch_get_delta(patch);
const git_oid &id = (!oldFile) ? dd->new_file.id : dd->old_file.id;
git_object *obj = nullptr;
git_object_lookup(&obj, repo, &id, GIT_OBJECT_ANY);
git_blob* blob = reinterpret_cast<git_blob *>(obj);
const char* pointer = (const char*)git_blob_rawcontent(blob);
// cleanup
git_object_free(obj);
git_patch_free(patch);
git_diff_free(diff);
git_repository_free(repo);
return 0;
}
The repository
create a new repository
commit a file like:
1
2
3
4
remove the 4 again, but do not commit
let the program run
Expected:
The program runs fine.
Observed:
obj is still a nullptr after executing
git_object_lookup()
When setting the variable oldFile to true, the program runs fine and the pointer "pointer" contains the raw blob.
Does anybody know why I don't get a valid object from git_object_lookup() back?
The problem is that you're trying to get an object of id dd->new_file.id. This file is in the working directory, as it hasn't been added or committed yet. This means it isn't in the repository yet. When you run git_object_lookup(), it can't find the object as it hasn't been added to the tree. The OID doesn't correspond to any match so it returns null.
If you want to get the current working directory data, you must first create the object in the tree using git_blob_create_from_workdir, and then when trying to access it, it would be found. So your new code might look like:
bool oldFile = false;
const git_diff_delta *dd = git_patch_get_delta(patch);
git_oid id;
if (!oldFile) {
error = git_blob_create_from_workdir(&id, repo, dd->new_file.path);
if (error < 0) {
const git_error *e = git_error_last();
printf("Error %d/%d: %s\n", error, e->klass, e->message);
exit(error);
}
} else {
id = dd->old_file.id;
}
git_object *obj = nullptr;
git_object_lookup(&obj, repo, &id, GIT_OBJECT_ANY);
git_blob* blob = reinterpret_cast<git_blob *>(obj);
const char* pointer = (const char*)git_blob_rawcontent(blob);
When you diff between the index and the workdir, the new side of the delta represents the file in the working directory. Its id is the hash of the file on disk. Unless you explicitly insert that blob into the repository's object store by some other means, there's no reason for it to be there yet.
I need to know at which offset into an xml string a specific arbitrary node somewhere in dom can be found after xmlReadMemory was used to get dom. The problem is I can't figure out where to get the xmlParserCtxtPtr from to pass as first argument to xmlParserFindNodeInfo because my entire process of parsing yields no such context; only a xmlDoc.
The following code worked for me (libxml2 documentation leaves little to desire, had to download source code and dig in the lib until I understood enough to hack this together). The key is:
xmlSetFeature(ctxt, "gather line info", (void *)&v);
Here is some code to illustrate:
const char *xml = ...
xmlParserCtxt *ctxt = NULL;
xmlDoc *doc = NULL;
if (!(ctxt = xmlCreateDocParserCtxt((const unsigned char *)xml)))
return -1;
int v = 1;
xmlSetFeature(ctxt, "gather line info", (void *)&v);
if (xmlParseDocument(ctxt) == -1)
{
xmlFreeParserCtxt(ctxt);
return -1;
}
else
{
if ((ctxt->wellFormed) || ctxt->recovery)
doc = ctxt->myDoc;
else
{
xmlFreeParserCtxt(ctxt);
return -1;
}
}
// use doc to get a node and then xmlParserFindNodeInfo(ctxt, node)
…
xmlFreeParserCtxt(ctxt);
I'm trying to call execv after manually saerching for the program to execute.
In my case,
c is a struct which has args as an array of strings having the arguments passed while receiving input. nargs is the number of arguments.
c->args[0] would contain "ls","cat" etc.
I tried printing the value of the args[0], fullPath etc. in my child process. They all show values like "/bin/ls","/bin/cat" etc. But when I call execv, it returns -1 with an errno of 2, which I understand is the error for "No such file or directory". But I'm sure the file is there because thats what my PathResolver is returning after checking all permissions.
Can anyone point where I might have made a mistake.
//The part happening inside child
char *fullPath = PathResolver(c->args[0],1,&permission);
printf("FullPath: %s -- Permission: %d\n",fullPath,permission);
if(permission==0)
{
fprintf(stderr, "%s: Command not found\n",c->args[0]);
}
else if(permission==-1)
{
fprintf(stderr, "%s: Permission denied\n",c->args[0]);
}
else
{
char* args[c->nargs+1];
int m=0;
for(m=0;m<c->nargs;m++)
{
strcpy(args[m],c->args[m]);
}
args[c->nargs] = NULL;
printf("%d\n",execv(args[0], args));
printf("errno: %d\n",errno);
}
PathResolver function
char* PathResolver(char *command, int ResolverMode, int *Permission)
{
*Permission = 0;
char *returnString;
returnString = malloc((sizeof(char)));
char *strPath = getenv("PATH");
char *del = ":";
char *strToken = strtok(strPath,del);
FILE *f;
while(strToken)
{
char filePath[100];
sprintf(filePath,"%s/%s",strToken,command);
if(access(filePath,F_OK)>=0)
{
if(access(filePath,X_OK)>=0)
{
*Permission = 1;
sprintf(returnString,"%s%s ",returnString,filePath);
if(ResolverMode == 1)
break;
}
else
{
*Permission = -1;
}
}
strToken = strtok(NULL,del);
}
sprintf(returnString,"%s\b",returnString);
return returnString;
}
strcpy(args[m],c->args[m]); is undefined behaviour, because args[m] is not a pointer to valid memory.
The following might be simpler:
char * args[c->nargs + 1];
for (size_t m = 0; m != c->nargs; ++m)
{
args[m] = c->args[m];
}
args[c->nargs] = NULL;
There's no need to copy the strings.
(This may not be your actual problem, but it certainly prevents your program from being correct.)
execv() expects the program name to be prefixed by a full path as 1st parameter.
To have PATH searched instead of providing a path use execvp().
Update:
Also this line
returnString = malloc((sizeof(char)));
does only allocate 1 byte to returnString, which is way to few for how you use returnString.
I can get the subject alternative name like
X509_NAME_get_text_by_NID(X509_get_subject_name(x), NID_subject_alt_name, hc->https_domain_name, 256)
With same method by changing 2. parameter to NID_issuer_alt_name I am expecting to get issuer name like;
X509_NAME_get_text_by_NID(X509_get_subject_name(x), NID_issuer_alt_name, hc->https_ca_name, 256);
But instead I am getting a empty string . How can I retrieve issuer alternative name correctly?
You could try the following solution, as recommended in https://github.com/iSECPartners/ssl-conservatory :
static HostnameValidationResult matches_subject_alternative_name (const char *hostname, const X509 *server_cert) {
HostnameValidationResult result = MatchNotFound;
int i;
int san_names_nb = -1;
STACK_OF(GENERAL_NAME) *san_names = NULL;
// Try to extract the names within the SAN extension from the certificate
san_names = X509_get_ext_d2i((X509 *) server_cert, NID_subject_alt_name, NULL, NULL);
if (san_names == NULL) {
return NoSANPresent;
}
san_names_nb = sk_GENERAL_NAME_num(san_names);
// Check each name within the extension
for (i=0; i<san_names_nb; i++) {
const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
if (current_name->type == GEN_DNS) {
// Current name is a DNS name, let's check it
char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
// Make sure there isn't an embedded NUL character in the DNS name
if (ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
result = MalformedCertificate;
break;
}
else { // Compare expected hostname with the DNS name
if (strcasecmp(hostname, dns_name) == 0) {
result = MatchFound;
break;
}
}
}
}
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
return result;
}
Hope it helps !
In your call to X509_NAME_get_text_by_NID with the NID_issuer_alt_name constant, I would have replaced X509_get_subject_name(x) by X509_get_issuer_name(x). I think this should do the trick you are after.