C# PHP-CGI with cookie support - c#

I´m trying to create a WebServer and it´s working with HTML, Images...
But I want to implement PHP and I have a working implementation of PHP-CGI but it doesn't work with stuff like 'file_get_contents' and cookies.
And I was wondering if there is a way to fix that?
private string ProcessPHP(string phpPath, CookieCollection cookies)
{
Process CGI = new Process();
CGI.StartInfo.FileName = "php\\php.exe";
CGI.StartInfo.CreateNoWindow = true;
CGI.StartInfo.Arguments = "-q \"" + phpPath + "\"";
CGI.StartInfo.RedirectStandardOutput = true;
CGI.StartInfo.UseShellExecute = false;
CGI.Start();
string OutputText = CGI.StandardOutput.ReadToEnd();
CGI.WaitForExit();
CGI.Close();
return OutputText;
}
And I know that I´m not doing anything with the CookieCollection but I want to know how to use it.
Thank you!

This is an old question, but currently the windows version of php ships with a separate php-cgi.exe. That's the executable you'll have to run.
With CGI, script information and request headers are sent via environment variables, ie:
CGI.StartInfo.info.EnvironmentVariables["SCRIPT_FILENAME"] = #"c:/wwwroot/index.php";
For a more elaborate example see https://en.wikipedia.org/wiki/Common_Gateway_Interface
HTTP headers such as cookies are also sent via environment variables. They are prefixed with 'HTTP_' and dashes are converted to underscores:
CGI.StartInfo.info.EnvironmentVariables["HTTP_COOKIE"] = ...
If your request body contains data, you have to set the CONTENT_LENGTH environment variable and write the data to the CGI.StandardInput after starting the process.

Related

Could not create SSL/TLS secure channel "http://www.rtvs.sk/televizia/archiv"

I am very new to ssl/tls, so please be patient. The code works for me few months for another sites (iprima.cz for example), but dont working for rtvs.sk.
it writes: Could not create SSL/TLS secure channel.
I have tried everything, but nothing works. Please help me.
string url1 = "https://www.rtvs.sk/televizia/archiv";
ServicePointManager.SecurityProtocol = (SecurityProtocolType)(0xc0 | 0x300 | 0xc00);
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => true;
//It is because I have tried enerything
string rets = "";
using (WebClient wc = new WebClient())
{
wc.Proxy = null;
int i = 0;
zatry:
try
{
Stream stream = wc.OpenRead(url1);
Encoding kod = Encoding.UTF8;
StreamReader sr = new StreamReader(stream, kod);
rets = sr.ReadToEnd();
sr.Close();
}
It seems to me to be site-specific, it works on Opera and other browsers, but not on my code.
It maybe a simple thing, but after reviewing all solutions for 5 hours and nothing works, I need a help. Thank you very much
Microsoft .NET Framework 4.7.03062SP1Rel
It has the same error on Microsoft Visual Studio 2010 and 2019 version 16.4.3
Introduction
It seems like the https://www.rtvs.sk/ server uses a not standard way of communication, that is not supported in .NET Framework libraries.
The server redirects any HTTP connection to HTTPS connection and this can not be avoided.
To bypass the "Could not create SSL/TLS secure channel" error you need to use a different HTTPS client. And I do not mean use the WebRequest.Create instead of the WebClient. The error is still here as this was the code I used in my application. A communication error is probably somewhere deeper in system since even Internet Explorer does not open the page (at least not in Windows 7).
There are a few possible options of an alternate client:
Write your own client from scratch - I cannot recommend this solution, it is hard, prone to errors...
Buy an existing alternative client - I found only one alternative HTTPS client for C# and the price was high. Too much for my simple personal application.
Use an alternative external client - e.g. wget, or an other downloader (custom and/or existing).
Try to use the application from Linux (or Mono framework). I did not test this solution but it is (at least theoretically) possible that the problem can be solved this way.
My Solution
After a simple test I found out, that there is no problem when downloading using Python. So I made a simple Python downloader and use it from my C# application.
The code in C# is:
private const string PythonSciptPath = "PythonDownloader.py";
private static bool UseStandardDownloader(string address) =>
!address.StartsWith("https://www.rtvs.sk/", StringComparison.Ordinal);
private static byte[] GetData(string address)
{
var start = new ProcessStartInfo
{
FileName = "python.exe",
Arguments = PythonSciptPath + " \"" + address + "\"",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
string result;
using (Process process = Process.Start(start))
using (StreamReader reader = process.StandardOutput)
{
result = reader.ReadToEnd();
}
return Convert.FromBase64String(result);
}
The code in Python (the "PythonDownloader.py" file) is:
import base64
import sys
import urllib.request
opener = urllib.request.URLopener()
stream = opener.open(sys.argv[1])
while True:
contentBytes = stream.read(60)
if len(contentBytes) == 0:
break
contentbase64Bytes = base64.b64encode(contentBytes)
contentString = contentbase64Bytes.decode("UTF-8")
print(contentString)
A simple way how to work with this is to add the file to project and select "Copy to output directory" option to "Copy if newer".
The current simple solution the code does not handle any error. I leave that part to you.
I also tried to use IronPython, but the simple client I wrote did not work because of a missing library. And it is possible that it will not work because it uses the .NET Framework libraries as interpreter.

C# not able to get console Logs from PhantomJSDriver (Selenium)

I'm using Selenium in C# with the PhantomJS Driver.
I need to click specific coordinates on a website, that works with using Javascript (im using the ExecutePhantomJS(string script) function of the selenium phantomjs driver). I also need to capture the network traffic. I used browsermob earlier to do that, but for now i cant use it because i also need to use another proxy. So i solved it like that until now:
//Hide CMD of PhantomJS.exe
var driverService = PhantomJSDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
//Initialize Driver and execute Network Script to capture traffic
driver = new PhantomJSDriver(driverService);
driver.ExecutePhantomJS(networkScript);
//Call URL
driver.Navigate().GoToUrl(url);
This is the networkScript:
string networkScript = "var page = this; page.onResourceRequested = function(req) { console.log('received: ' + JSON.stringify(res, undefined, 4)); }; page.onResourceReceived = function(res) { console.log('received: ' + JSON.stringify(res, undefined, 4)); };";
The good thing:
URL is called and all network traffic is logged into the console of the PhantomJS.exe.
But I dont know how I can get these console logs now in my C# code (I need to get specific things like URLs etc.. out of the network log).
I already read the whole afternoon but couldn't find a solution until now. Some of the things I already tried:
1) Tried to use PhantomJSOptions, there u can set LoggingPreferences and later i called driver.Manager().Logs.GetLog(LogType), but there were none of the console logs
2) Dont use console.log inside networkScript. I used require('system').stdout.write(...). It was also logged into console but I cant get the standard output stream of the phantomjs.exe from my C# code.
...
I really dont know how i could solve the problem.
One way would be to log into a .txt file instead of console, but it is very much text and later there will be many opened drivers, so I want to avoid that because then i will have very much and big .txt files

Trying to use Twitter from console application.Credentials somehow are stored the wrong way

I made a console application usin Tweetinvi c# library. My project is almost complete if i solve this problem.
Everytime I use Tweetinvi and set the credentials typing the keys directly into the code it works fine and publishes tweets so I know that command works. However I need to store the credentials in a file parse them to substring and clear them from spaces etc.Parsing is successful since i checked with console.writeline. When use variables to set the keys in tweetinvi authoriatization nothing happens wich mean I 'm making a mistake when clearing my substrings. Consolle.Writelines shows nothing and credentials dont work.Any help?`
{
AccessToken = AccessToken.Replace(#"\r\n", "");
AccessToken = AccessToken.Trim();
Console.WriteLine(AccessToken);
AccessTokenSec = AccessTokenSec.Replace(#"\r\n", "");
AccessTokenSec = AccessTokenSec.Trim();
Console.WriteLine(AccessTokenSec);
var creds = new TwitterCredentials("consumerkei", "consumerkeysecret",AccessToken.Trim(),AccessTokenSec.Trim());
Auth.SetCredentials(creds);
var firstTweet = Tweet.PublishTweet("Hello World! Again!");
}
`

Need simple Powershell output appended to Google sheet

I'm having a very hard time with what I feel should be a simple task. Every week, our team queries VMware vCenter for three pieces of output: VM counts in three different locations. Here is what it looks like:
Name Value
---- -----
locationA 1433
locationB 278
locationC 23
The information is emailed to our team, as well as some of the higher-ups who like to see the data. This is all automated with a Powershell script and Windows Task Scheduler running on a server, no problems.
That data is also placed in a Google sheet. We just append a new row with the date, and copy and paste the data into the three existing columns. It takes 30 seconds, once a week. Seems silly given how little time it takes to copy it over to the Google sheet but I really want to automate that last process using Google Sheets API.
I seem to keep finding and persuing what feel are online wild goose chases, in the Google scripting to accessing and editing Google sheets. I've downloaded and installed the Sheets API libraries, Drive API libraries, the Google .net library, set up the Google developer site, and run through the Google sheets API documentation and OAuth authenticating. I'm using Visual Studio 2013 because I figured that would play the best with Powershell and calling the .net commands.
I have pretty much no coding experience outside of Powershell (if you can call that coding). I can't even figure out how to pull the Google sheet, much less do anything to it. Nothing I've tried is working so far, and for what little time it takes to copy this info manually every week I've already spent so much more time than is probably worth it. I feel like if I can get a handle on this, that would open the door for further Google automation in the future since we operate with a Google domain. At any rate, help is very much appreciated.
Here is my latest scripting attempt in Visual Studio:
using System;
using Google.GData.Client;
using Google.GData.Spreadsheets;
namespace MySpreadsheetIntegration
{
class Program {
static void Main(string[] args)
{
string CLIENT_ID = "abunchofcharacters.apps.googleusercontent.com";
string CLIENT_SECRET = "secretnumber";
string REDIRECT_URI = "https://code.google.com/apis/console";
OAuth2Parameters parameters = new OAuth2Parameters();
parameters.ClientId = CLIENT_ID;
parameters.ClientSecret = CLIENT_SECRET;
parameters.RedirectUri = REDIRECT_URI;
parameters.Scope = SCOPE;
string authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
Console.WriteLine(https://code.google.com/apis/console);
Console.WriteLine("Please visit the URL above to authorize your OAuth "
+ "request token. Once that is complete, type in your access code to "
+ "continue..."));
parameters.AccessCode = Console.ReadLine();
OAuthUtil.GetAccessToken(parameters);
string accessToken = parameters.AccessToken;
Console.WriteLine("OAuth Access Token: " + accessToken);
GOAuth2RequestFactory requestFactory =
new GOAuth2RequestFactory(null, "MySpreadsheetIntegration-v1", parameters);
SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
service.RequestFactory = requestFactory;
var driveService = new DriveService(auth);
var file = new File();
file.Title = "VSI - VM Totals by Service TEST";
file.Description = string.Format("Created via {0} at {1}", ApplicationName, DateTime.Now.ToString());
file.MimeType = "application/vnd.google-apps.spreadsheet";
var request = driveService.Files.Insert(file);
var result = request.Fetch();
var spreadsheetLink = "https://docs.google.com/spreadsheets/d/GoogleDoc_ID";
Console.WriteLine("Created at " + spreadsheetLink);
End Class;
End Namespace;
}
}
}
For anyone still following this, I found a solution. I was going about this entirely the wrong way (or at least a way that I could comprehend). One solution to my issue was to create a new Google Script that only accessed my email once a week (after we got the report) and teased out everything but the data I was looking for and sent it to the Google spreadsheet.
Here's the script:
function SendtoSheet(){
var threads = GmailApp.search("from:THESENDER in:anywhere subject:THESUBJECTOFTHEEMAILWHICHNEVERCHANGES")[0];
var message = threads.getMessages().pop()
var bodytext = message.getBody();
counts = []
bodytext = bodytext.split('<br>');
for (var i=0 ; i < bodytext.length; i++){
line = bodytext[i].split(':');
if (line.length > 0){
if (!isNaN(line[1])){counts.push(line[1]);}}}
var now = new Date()
counts.unshift(Utilities.formatDate(now, 'EST', 'MM/dd/yyyy'))
var sheet = SpreadsheetApp.openById("GoogleDocID")
sheet = sheet.setActiveSheet(sheet.getSheetByName("Data by Week"))
sheet.appendRow(counts)
}
That Counts array contains the magic to extract the numeric data by breaking up by line breaks and :'s. Works perfectly. It didn't involve figuring out how to use Visual Studio, or the .net Google libraries, or editing the running PowerShell script. Clean and easy.
Hope this helps someone.

C# git command line process

Our organization utilizes VisualStudioOnline, GitHub and BitBucket for various repositories. I've been trying to figure out a way in c# to automate the pull of changes from various git repositories on a regular schedule. I've tried starting a process like this and then redirecting the standard input/output.
var p = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"C:\Program Files (x86)\Git\bin\sh.exe",
RedirectStandardInput = true,
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = "--login -i"
}
};
p.Start();
using (var so = p.StandardOutput)
{
using (var si = p.StandardInput)
{
if (si.BaseStream.CanWrite)
{
...
}
}
}
Inside of the block, I'm able to execute git commands like this:
si.WriteLine("cd \"P:/code/testapp\""); which navigates the git
shell to that directory
si.WriteLine("git rev-parse HEAD");
which will give me the latest hash of the repository at that location.
I can see the hash returned in the bash shell and can also read it in through the standard input like this var hash = so.ReadLine();
When I try to do si.WriteLint("git pull"); though, it asks for username and password, which I would expect, but that isn't done through the standard input/output. I can't us var prompt = so.ReadLine(); to get the prompt for username or password and I can't use si.WriteLine("username"); to input my password to the prompt.
I've tried a number of things to get this to work, but so far no luck.
WARNING: messy code ahead, just tried to quickly prototype something, not create a masterpiece
Attempt 1: used standard input/output redirects as shown above to try to write/read the prompts for username/password.
Attempt 2: attempt to get the ssh-agent process that is being utilized by the git bash and write to it
si.WriteLine("ssh-agent --help");
var sshAgentInfo = string.Empty;
var tmp = a.ReadLine();
while (a.Peek() != -1)
{
sshAgentInfo += tmp;
tmp = a.ReadLine();
}
var begPos = sshAgentInfo.IndexOf("SSH_AGENT_PID=", StringComparison.Ordinal);
begPos = begPos + "SSH_AGENT_PID=".Length;
var endPos = sshAgentInfo.IndexOf(";", begPos, StringComparison.Ordinal);
var processId = int.Parse(sshAgentInfo.Substring(begPos, endPos - begPos));
var sshProcess = Process.GetProcessById(processId);
sshProcess.StartInfo.RedirectStandardInput = true;
sshProcess.StartInfo.RedirectStandardInput = true;
using (var si1 = sshProcess.StandardInput) { ... }
Attempt 3: Utilize credential git config credential.helper wincred
This and four were very similar attempts. Again just trying to figure out how to set the password in either of these credential managers from the command line.
Attempt 4: Utilize Git-Credential-Manager-for-Windows
I've tried looking through the documentation here and it seems as though there is an enhancement request to do something along these lines.
Both of these seem to have similar problems to attempt one. The git shell seems to be invoking another process which handles the standard input and output separate from the git shell. The difference and hope I have for these last two though is, Is there a way to call into those credential managers directly to set username/passwords for different urls? In the .git directory, the config file has the credentials setting to tell it which manager to use and it stores the username and email in plain text.
If I invoke a git pull through the shell on the machine and enter my credentials once through that shell it seems to store them, but is there a way to allow users to enter their credentials through a website and then call into the manager through the command line to securely store that information for future automated use?
I also came across this. I haven't had a chance to try it yet, but is this a viable option for doing something like this?
Any help would be greatly appreciated.

Categories