Top level domain ignorance at using RIPE - c#

I'm developing a simple app in c#, that can check if a domain name is available to puchase for a specific tld.
The method: I downloaded a whois-server list, I send the domain name to its whois server with a TCP client on the protocol 43, and check the servers answer.
The problem: more countries has the same whois server: "whois.ripe.net" .
If I send the full domain name(with tld), the server's answer is always "No entries found in source RIPE.". If I send the domain name without tld, I dont get any tld specific data about the status of the domain name.
The method I use:
private string GetWhoisInformation(string whoisServer, string url)
{
try
{
StringBuilder stringBuilderResult = new StringBuilder();
TcpClient tcpClinetWhois = new TcpClient(whoisServer, 43);
NetworkStream networkStreamWhois = tcpClinetWhois.GetStream();
BufferedStream bufferedStreamWhois = new BufferedStream(networkStreamWhois);
StreamWriter streamWriter = new StreamWriter(bufferedStreamWhois);
streamWriter.WriteLine(url);
streamWriter.Flush();
StreamReader streamReaderReceive = new StreamReader(bufferedStreamWhois);
while (!streamReaderReceive.EndOfStream)
stringBuilderResult.AppendLine(streamReaderReceive.ReadLine());
return stringBuilderResult.ToString();
}
catch
{
return "lekérdezés sikertelen";
}
}
Example:
I do:
GetWhoisInformation("whois.ripe.net", "pokerstars.hu")
The server's answer:
%ERROR:101: no entries found
%
% No entries found in source RIPE.
for the next command:
GetWhoisInformation("whois.ripe.net", "pokerstars")
the result contains several blocks like this:
% Information related to '80.65.254.128 - 80.65.254.159'
inetnum: 80.65.254.128 - 80.65.254.159
netname: Pokerstars
descr: Hosting
country: GB
admin-c: DC77-RIPE
tech-c: JM2352-RIPE
status: assigned PA
mnt-by: manx-telecom-mnt
changed: bill.hogg#manx-telecom.com 20101123
source: RIPE
There's no information about the domain name "pokerstars.hu". Of course, I get exactly the same answers if I want to check pokerstars.va. Pokerstars.hu is a registred domain, pokerstars.va is not.
How can I find the correct status of a domain name?

RIPE does not serve as a ccTLD whois server for any domains; like ARIN, it contains only netblock information. Each ccTLD has its own root whois server (or, that is, some of them don't have a proper whois service -- for example, the Spanish .es registry requires that you use a web client, with an obnoxious CAPTCHA you have to fill in every time).
See also http://www.ripe.net/data-tools/db although it is not very explicit about what the database does not contain.
You can get the address of the authoritative whois server by requesting the ccTLD's information from whois.iana.org.
vnix$ whois -h whois.iana.org hu | fgrep whois:
whois: whois.nic.hu
See also http://www.iana.org/domains/root/db/

I tried your code against whois.melbourneit.net and it found one of my domains no trouble. I was able to reproduce your problem running against RIPE and so I tried the same query interactively on their website - and had the same result. There's nothing wrong with your code.
tripleee is right about whois.nic.hu, I successfully used it to resolve pokerstars.hu - which leaves me wondering what the blazes is purpose of the RIPE whois server.
Thanks to triplee for showing us how to obtain the whois server friendly-name for a ccTLD.
You may find this useful:
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
namespace Whois
{
class Program
{
static void Main(string[] args)
{
string tldWhoisServer = "whois.iana.org";
string ccTldServer, query = null;
Console.Write("Query> ");
while ((query = Console.ReadLine()) != string.Empty)
{
string tld = query.Substring(query.LastIndexOf('.') + 1);
string foo = GetWhoisInformation(tldWhoisServer, tld);
foo = foo.Remove(0, foo.IndexOf("whois:") + 6).TrimStart();
ccTldServer = foo.Substring(0, foo.IndexOf('\r'));
Console.WriteLine(GetWhoisInformation(ccTldServer, query));
Console.Write("Query> ");
}
}
static string GetWhoisInformation(string whoisServer, string url)
{
try
{
StringBuilder stringBuilderResult = new StringBuilder();
TcpClient tcpClinetWhois = new TcpClient(whoisServer, 43);
NetworkStream networkStreamWhois = tcpClinetWhois.GetStream();
BufferedStream bufferedStreamWhois = new BufferedStream(networkStreamWhois);
StreamWriter streamWriter = new StreamWriter(bufferedStreamWhois);
streamWriter.WriteLine(url);
streamWriter.Flush();
StreamReader streamReaderReceive = new StreamReader(bufferedStreamWhois);
while (!streamReaderReceive.EndOfStream)
stringBuilderResult.AppendLine(streamReaderReceive.ReadLine());
return stringBuilderResult.ToString();
}
catch
{
return "Query failed";
}
}
}
}

Related

Xamarin.Android TcpClient not working sometimes

I'm trying to create an application where I have to use WHOIS to get some information I need.
To get the WHOIS information I use this function I found on here and adjusted a little:
string Whois(string domain, string whoisServer = "whois.iana.org")
{
string toReturn = "";
TcpClient tcpClinetWhois = new TcpClient(whoisServer, 43);
MemoryStream memoryStreamWhois = new MemoryStream();
Task copying = tcpClinetWhois.GetStream().CopyToAsync(memoryStreamWhois);
StreamWriter streamWriter = new StreamWriter(tcpClinetWhois.GetStream());
streamWriter.WriteLine(domain);
streamWriter.Flush();
copying.Wait(3000);
toReturn = Encoding.ASCII.GetString(memoryStreamWhois.ToArray());
if (toReturn.Contains("refer:"))
{
toReturn = Whois(domain, toReturn.Split('\n').Where(W => W.StartsWith("refer:")).Select(R => R.Replace("refer:", "").Trim()).First());
}
return toReturn;
}
When I run it, it works for most TLDs like .com or .org but not for .co.uk or .network and probably others too. I have no idea why it wouldn't work because the right WHOIS server gets selected for the TLD. I am also not getting any errors.
I'm using .Net7.0 and my Android 11 phone for testing.
I've tested this exact same function with the exact same domains on the same network but in a Console Application with no problems at all! Everything works fine except when I try this function in a Xamarin Application.

Check Load Balancing server using C#

I have four application server for my application.Application is working on all server using load balancing.If one of my server goes down I have to check it manually using my system hosts file.To avoid this manual process I have created one program using C#.I write server IP address one by one in host file and remove previous one.
private void RunWithUAC()
{
List<string> lstIPAddress = new List<string>();
lstIPAddress.Add("1.1.1.1 example.com");
lstIPAddress.Add("1.1.1.1 example.com");
lstIPAddress.Add("1.1.1.1 example.com");
lstIPAddress.Add("1.1.1.1 example.com");
var systemPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
Console.WriteLine(systemPath);
var path = #"C:\Windows\System32\drivers\etc\hosts";
foreach (var item in lstIPAddress)
{
System.IO.File.WriteAllText(path, string.Empty);
try
{
File.WriteAllText(path, item);
WebRequest request = WebRequest.Create("https://example.com");
request.Timeout = 10000;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
catch (Exception)
{
MessageBox.Show(item);
}
Thread.Sleep(1000);
}
}
But When second server goes down.It will give me timeout error for third server.
Please check the code and let me know what is wrong with this code.
Probably some kind of connection pooling, HTTP pipelining or keep-alive. This is the wrong approach in the first place.
Connect directly to the right IP (WebRequest.Create("https://1.1.1.1")). If you need to send a Host header add that manually to the request.

Email client app exceptions

I am developing an app with xamarin studio. My goal is to connect to pop3 and download emails to my app.
I am using the following code but I am facing these issues:
a) an exception on sslstream.AuthenticateAsClient("pop.gmail.com");. (The authentication or decryption has failed).
b)everywhere I have sw.Flush() I am taking exception: This operation is invalid until it is successfully authenticated.
TcpClient tcpclient = new TcpClient();
tcpclient.Connect("pop.gmail.com", 995);
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
sslstream.AuthenticateAsClient("pop.gmail.com");
StreamWriter sw = new StreamWriter(sslstream);
System.IO.StreamReader reader = new StreamReader(sslstream);
sw.WriteLine("USER myusername");
sw.Flush();
sw.WriteLine("PASS *****");
sw.Flush();
sw.WriteLine("RETR 1");
sw.Flush();
sw.WriteLine("Quit ");
sw.Flush();
string str = string.Empty;
string strTemp = string.Empty;
while((strTemp = reader.ReadLine()) !=null){
if(".".Equals(strTemp)){
break;
}
if(strTemp.IndexOf("-ERR") != -1){
break;
}
str +=strTemp;
}
reader.Close();
sw.Close();
tcpclient.Close();
EDIT
I used mailkit and it is a great solution. I can retrieve emails but i have a problem. When i have download a number of mails(not specific number. For deferent account was deferent number of mails)
I am taking the following error:
system.ArgumentOutOfRangeException on: var message = client.GetMessage(i, cancel.Token);
My code for the login:
partial void btnlogin (NSObject sender)
{
using (var client = new Pop3Client ()) {
var credentials = new NetworkCredential (Convert.ToString(txtusername.Text).Trim(), Convert.ToString(txtpassword.Text).Trim());
// Note: if the server requires SSL-on-connect, use the "pops" protocol instead
var uri = new Uri (Convert.ToString("pops://pop.gmail.com"));
using (var cancel = new CancellationTokenSource ()) {
client.Connect (uri, cancel.Token);
client.Authenticate (credentials, cancel.Token);
int count = client.GetMessageCount (cancel.Token);
var list= new List<string>();
for (int i = 0; i < count; i++) {
var message = client.GetMessage (i, cancel.Token);
Console.WriteLine ("From: {0}", message.From);
list.Add(Convert.ToString(message.From));
}
client.Disconnect (true, cancel.Token);
}
}
}
I came here to suggest using MailKit instead of writing your own library for this. MailKit is also specifically meant to work with Xamarin (since I work at Xamarin). MailSystem.NET is pretty badly broken (I've ranted about it elsewhere on StackOverflow), so I would definitely not recommend using that.
That said, you may need to look at using this version of the SslStream .ctor as opposed to the one you are using. The problem may be that the default .ctor isn't validating the SSL certificate because it isn't "trusted".
I would use an existing C# library to do this.
At one point in the past, I used MailSystem.NET and was able to port their library to MonoTouch. I am not sure of its license works for you, but you will have a much better time using it than rolling your own.
I also think that writing your own library for this would be a waste of anyone's time. I haven't tried Mail Kit yet (will definitely have to), but I have recently used Rebex Mail when I needed to backup my emails from my email server via POP3. Fortunatelly, it was a one time task only, so I did not have to pay as I only used their 30-day free trial that did not have any limitation.
using Rebex.Mail;
using Rebex.Net;
Pop3 client = new Pop3();
client.Connect("pop.gmail.com", SslMode.Implicit);
client.Login("gmailuser", "password");
var messageInfos = client.GetMessageList(Pop3ListFields.FullHeaders);
foreach (Pop3MessageInfo message in messageInfos)
client.GetMessage(message.SequenceNumber, string.Format(#"C:\gmail-pop3-backup\{0}-{1}.eml", message.Subject, message.UniqueId));
client.Disconnect();

create a directory with subdirectories in a single ftp request?

I got a small problem on how to create a directory with subdirectories in a single ftp request
I have a string s
string s = "a/b/c/d"
NOTE : The words between slashes are random and the number of items is unknown.
How to create in the FTP server the directory a/b/c/d ????
The way i'm using to achieve this is to split the string and create a folder for each part using the code below :
var ftpWebRequest = (FtpWebRequest)WebRequest.Create("ftp://domain.com/public_html/a");
ftpWebRequest.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
ftpWebRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
ftpWebRequest.GetResponse();
Then i create the b directory inside a, then c inside b, then d inside c by repeating some code, each time
I tried to type the url directly. like :
var ftpWebRequest = (FtpWebRequest)WebRequest.Create("ftp://doemin.com/public_html/a/b/c/d);
but it doesn't work.
Is there a short way on how can i create a folder with other subdirectories in a one single request ?
If you are willing to use a more friendly library (free and open source) like this one:
System.Net.FtpClient.dll
then you could write code like this (adapted from their example)
static ManualResetEvent m_reset = new ManualResetEvent(false);
void Main()
{
m_reset.Reset();
using (FtpClient ftp = new FtpClient())
{
ftp.Host = "yourFTPHost.com";
ftp.Credentials = new NetworkCredential("yourUserName", "yourPassword");
ftp.SetWorkingDirectory("/rootForTest");
if(ftp.DirectoryExists("test"))
ftp.DeleteDirectory("test", true);
ftp.BeginCreateDirectory("test/path/that/should/be/created", true,
new AsyncCallback(CreateDirectoryCallback), ftp);
m_reset.WaitOne();
ftp.Disconnect();
}
}
static void CreateDirectoryCallback(IAsyncResult ar)
{
FtpClient ftp = ar.AsyncState as FtpClient;
try
{
if (ftp == null)
throw new InvalidOperationException("The FtpControlConnection object is null!");
ftp.EndCreateDirectory(ar);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
m_reset.Set();
}
}
A side note: System.Net.FtpClient requires the full NET 4.0 Framework. (Cliente Profile is not enough)
Some servers do support FTP commands like MKD a/b/c/d . If your server doesn't, but supports execution of shell commands via SITE command, you can try to call "SITE md a/b/c/d" (but this is machine-specific). If none of the above works, then you have to create folders in a loop like you do or use some library which hides this loop in a one method.

How to send arbitrary FTP commands in C#

I have implemented the ability to upload, download, delete, etc. using the FtpWebRequest class in C#. That is fairly straight forward.
What I need to do now is support sending arbitrary FTP commands such as
quote SITE LRECL=132 RECFM=FB
or
quote SYST
Here's an example configuration straight from our app.config:
<!-- The following commands will be executed before any uploads occur -->
<extraCommands>
<command>quote SITE LRECL=132 RECFM=FB</command>
</extraCommands>
I'm still researching how to do this using FtpWebRequest. I'll probably try WebClient class next. Anyone can point me in the right direction quicker? Thanks!
UPDATE:
I've come to that same conclusion, as of .NET Framework 3.5 FtpWebRequest doesn't support anything except what's in WebRequestMethods.Ftp.*. I'll try a third party app recommended by some of the other posts. Thanks for the help!
I don't think it can be done with FtpWebRequest... The only way to specify a FTP command is through the Method property, and the documentation states :
Note that the strings defined in the WebRequestMethods.Ftp class are the only supported options for the Method property. Setting the Method property to any other value will result in an ArgumentException exception.
SITE and SYST are not among the predefined options, so I guess you're stuck...
Don't waste time to try the WebClient class, it will give you even less flexibility than FtpWebRequest.
However, there are plenty of third-party FTP implementation, open source or commercial, and I'm pretty sure some of them can handle custom commands...
The FtpWebRequest won't help you as Thomas Levesque has said in his answer. You can use some third party solutions or the following, simplified TcpClient based code which I have refactored from an answer written in Visual Basic:
public static void SendFtpCommand()
{
var serverName = "[FTP_SERVER_NAME]";
var port = 21;
var userName = "[FTP_USER_NAME]";
var password = "[FTP_PASSWORD]"
var command = "SITE CHMOD 755 [FTP_FILE_PATH]";
var tcpClient = new TcpClient();
try
{
tcpClient.Connect(serverName, port);
Flush(tcpClient);
var response = TransmitCommand(tcpClient, "user " + userName);
if (response.IndexOf("331", StringComparison.OrdinalIgnoreCase) < 0)
throw new Exception(string.Format("Error \"{0}\" while sending user name \"{1}\".", response, userName));
response = TransmitCommand(tcpClient, "pass " + password);
if (response.IndexOf("230", StringComparison.OrdinalIgnoreCase) < 0)
throw new Exception(string.Format("Error \"{0}\" while sending password.", response));
response = TransmitCommand(tcpClient, command);
if (response.IndexOf("200", StringComparison.OrdinalIgnoreCase) < 0)
throw new Exception(string.Format("Error \"{0}\" while sending command \"{1}\".", response, command));
}
finally
{
if (tcpClient.Connected)
tcpClient.Close();
}
}
private static string TransmitCommand(TcpClient tcpClient, string cmd)
{
var networkStream = tcpClient.GetStream();
if (!networkStream.CanWrite || !networkStream.CanRead)
return string.Empty;
var sendBytes = Encoding.ASCII.GetBytes(cmd + "\r\n");
networkStream.Write(sendBytes, 0, sendBytes.Length);
var streamReader = new StreamReader(networkStream);
return streamReader.ReadLine();
}
private static string Flush(TcpClient tcpClient)
{
try
{
var networkStream = tcpClient.GetStream();
if (!networkStream.CanWrite || !networkStream.CanRead)
return string.Empty;
var receiveBytes = new byte[tcpClient.ReceiveBufferSize];
networkStream.ReadTimeout = 10000;
networkStream.Read(receiveBytes, 0, tcpClient.ReceiveBufferSize);
return Encoding.ASCII.GetString(receiveBytes);
}
catch
{
// Ignore all irrelevant exceptions
}
return string.Empty;
}
You can expect the following flow while getting through the FTP:
220 (vsFTPd 2.2.2)
user [FTP_USER_NAME]
331 Please specify the password.
pass [FTP_PASSWORD]
230 Login successful.
SITE CHMOD 755 [FTP_FILE_PATH]
200 SITE CHMOD command ok.
You can try our Rebex FTP component:
// create client and connect
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// send SITE command
// note that QUOTE and SITE are ommited. QUOTE is command line ftp syntax only.
client.Site("LRECL=132 RECFM=FB");
// send SYST command
client.SendCommand("SYST");
FtpResponse response = client.ReadResponse();
if (response.Group != 2)
; // handle error
// disconnect
client.Disconnect();
Use sendCommand("SITE LRECL=242 BLKSIZE=0 RECFM=FB");

Categories

Resources