connecting POP3 via http proxy using HigLabo - c#

I'm using HigLabo to create an email client. Also I need to use an http proxy.
But authentication fails every time.
I found the base code here : .net pop3 over http proxy
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HigLabo.Net;
using HigLabo.Net.Pop3;
using System.Net.Sockets;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static Pop3Client pop;
static Socket socket;
static void Main(string[] args)
{
String proxyAddr = "112.241.212.104"; //This seemed to be working
int proxyPort = 8585;
byte[] buffer = new byte[25];
pop = new Pop3Client("PopClient");
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
Console.WriteLine("Connecting to proxy...");
socket.Connect(proxyAddr, proxyPort);
Console.WriteLine("Connected to proxy");
Console.WriteLine("Sending Packets...");
socket.Send(Encoding.UTF8.GetBytes("CONNECT pop.mail.yahoo.com:995 HTTP/1.1<CR><LF>"));
socket.Send(Encoding.UTF8.GetBytes("<CR><LF>"));
Console.WriteLine("Packets sent");
Console.WriteLine("Waiting for response...");
socket.Receive(buffer);
Console.WriteLine("Packets received");
Console.WriteLine("Time Elapsed : " + timeElapsed + " seconds");
Console.WriteLine("Connectong POP to socket...");
if (pop.Connect(socket))
{
pop.Connect();
Console.WriteLine("Connection completed");
}
else
{
Console.WriteLine("Disconnected");
Disconnect();
return;
}
pop.Ssl = true;
pop.UserName = "EMAIL_ADDRESS";
pop.Password = "PASSWORD";
pop.ServerName = "pop.gmail.com";
pop.Port = 995;
Console.WriteLine("Authenticating...");
if (pop.Authenticate())
{
Console.WriteLine("Authentication completed"); //Never comes here
GetMail();
}
else
{
Console.WriteLine("Authentication failed"); //Always comes here
Disconnect();
}
}
private static void GetMail()
{
HigLabo.Mime.MailMessage msg = pop.GetMessage(1);
Console.WriteLine(msg.BodyText);
}
static void Disconnect()
{
Console.WriteLine("Disconnecting...");
pop.Close();
socket.Close();
Console.WriteLine("Disconnected");
}
}
}
I gave permission for the app also.
What is wrong here?
Are there any other/better/easy ways to do this? May be with a different library?

This is wrong: <CR><LF>.
What you want to use is \r\n in your strings.

Related

NetworkCommsDotNet , how can I reverse TCP client and server functions in this code?

EDIT
With all great functionality that NetworkCommsDotNet offers, it looks like this library is not actively supported anymore. I am changing direction to accept Eser's response as answer. I tested the provided code and it worked. Thanks for your help.
Below is my code of simple TCP client-server, based on NetworkCommsDotNet library. The client periodically sends changing positions of an "object" to the server, and the server displays them. This works fine, however, what I want to achieve is exactly the opposite: I want the client to only connect to the server, and once the server detects a connection, then it starts periodically sending some X and Y coordinates back to the client. I could not have this done with NetworkCommsDotNet, any help is appreciated.
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections.TCP;
namespace ObjectPositionClient
{
class Program
{
static void Main(string[] args)
{
try {
var conn = TCPConnection.GetConnection(new ConnectionInfo("127.0.0.1", 50747));
System.Timers.Timer tmer;
tmer = new System.Timers.Timer(3000);
tmer.Elapsed += (sender, e) => TimerElapsed(sender, e, conn);
tmer.Enabled = true;
Console.WriteLine("Press any key to exit client.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
catch (Exception e)
{
Console.WriteLine(e.InnerException + "\n" + e.Message);
}
}
static public void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e, TCPConnection conn)
{
Random rnd = new Random();
int X = rnd.Next(1, 101);
int Y = rnd.Next(1, 51);
conn.SendObject("Message", "X=" + X + "; Y=" + Y);
}
}
}
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections;
namespace ObjectPositionServer
{
class Program
{
static void Main(string[] args)
{
try
{
var con = Connection.StartListening(ConnectionType.TCP, new System.Net.IPEndPoint(System.Net.IPAddress.Any, 50747));
NetworkComms.AppendGlobalIncomingPacketHandler<string>("Message", PrintIncomingMessage);
Console.WriteLine("Server ready. Press any key to shutdown.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
catch (Exception e)
{
Console.WriteLine(e.InnerException + "\n" + e.Message);
}
}
private static void PrintIncomingMessage(PacketHeader header, Connection
connection, string message)
{
Console.WriteLine(message + "\n");
}
}
}
Here is a TCP based, basic, client/server sample. Whenever a client connects to server, server sends 10 strings to client and then close the connection. I think this is similar to your case.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
public class TCPTest
{
public static void StartAll()
{
Task.Run(() => StartServer());
Task.Run(() => StartClient());
}
static void StartServer()
{
TcpListener listener = new TcpListener(IPAddress.Any, 12345);
listener.Start();
Console.WriteLine("Server Started");
while (true)
{
var client = listener.AcceptTcpClient();
Console.WriteLine("A new client is connected");
ThreadPool.QueueUserWorkItem(ServerTask,client);
}
}
static void ServerTask(object o)
{
using (var tcpClient = (TcpClient)o)
{
var stream = tcpClient.GetStream();
var writer = new StreamWriter(stream);
for (int i = 0; i < 10; i++)
{
writer.WriteLine($"packet #{i + 1}");
writer.Flush();
Thread.Sleep(1000);
}
Console.WriteLine("Server session ended..");
}
}
static void StartClient()
{
TcpClient client = new TcpClient();
client.Connect("localhost", 12345);
var stream = client.GetStream();
var reader = new StreamReader(stream);
string line = "";
while((line = reader.ReadLine()) != null)
{
Console.WriteLine("Client received: "+ line);
}
Console.WriteLine("Client detected end of the session");
}
}
Use TCPTest.StartAll(); to start the test.
You can even telnet to this server. telnet localhost 12345
EDIT
Since you have commented, you want to transfer objects between client and server, I modified to code to show how it can be done (using Json.Net). This time, server sends 10 User objects to client.
I will post it as a new code, in case someone wants to see the minor differences.
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
public class TCPTest
{
//Sample class to transfer between server and client
public class User
{
public string Name { get; set; }
public int Id { get; set; }
public DateTime BirthDate { set; get; }
}
public static void StartAll()
{
Task.Run(() => StartServer());
Task.Run(() => StartClient());
}
static void StartServer()
{
TcpListener listener = new TcpListener(IPAddress.Any, 12345);
listener.Start();
Console.WriteLine("Server Started");
while (true)
{
var client = listener.AcceptTcpClient();
Console.WriteLine("A new client is connected");
ThreadPool.QueueUserWorkItem(ServerTask, client);
}
}
static void ServerTask(object o)
{
using (var tcpClient = (TcpClient)o)
{
var stream = tcpClient.GetStream();
var writer = new StreamWriter(stream);
for (int i = 0; i < 10; i++)
{
var user = new User() { Name = $"Joe{i}", Id = i , BirthDate = DateTime.Now.AddDays(-10000)};
var json = JsonConvert.SerializeObject(user);
writer.WriteLine(json);
writer.Flush();
Thread.Sleep(1000);
}
Console.WriteLine("Server session ended..");
}
}
static void StartClient()
{
TcpClient client = new TcpClient();
client.Connect("localhost", 12345);
var stream = client.GetStream();
var reader = new StreamReader(stream);
string json = "";
while ((json = reader.ReadLine()) != null)
{
var user = JsonConvert.DeserializeObject<User>(json);
Console.WriteLine($"Client received: Name={user.Name} Id={user.Id} BirthDate={user.BirthDate}");
}
Console.WriteLine("Client detected end of the session");
}
}

Tcp .Send Doesn't work after using for the first time

I am UsingClient.Send(Encoding.ASCII.GetBytes(Message)); to send a message to the client, when i tried sending a second message it doesn't give any error so i think it send with no problem but it never reaches the client (127.0.0.1)
Code That Send
public void SendMessage(Socket _Client, string Message)
{
foreach (Socket Client in Clients)
{
IPEndPoint TargetEndPoint = _Client.LocalEndPoint as IPEndPoint;
IPAddress TargetIp = TargetEndPoint.Address;
int TargetPort = TargetEndPoint.Port;
IPEndPoint ClientEndPoint = Client.LocalEndPoint as IPEndPoint;
IPAddress ClientIp = ClientEndPoint.Address;
int ClientPort = ClientEndPoint.Port;
if (TargetIp.ToString() == ClientIp.ToString() && TargetPort == ClientPort)
{
Client.Send(Encoding.ASCII.GetBytes(Message));
//Client.EndSend();
}
}
}
Code That Receive
private void RecivedCallBack(IAsyncResult Result)
{
//Create a int with the Buffer Size
int BufferSize = _Socket.EndReceive(Result);
//Create a new byte array with the Buffer Size
byte[] Packet = new byte[BufferSize];
//Copy Buffer to Packet
Array.Copy(_Buffer, Packet, Packet.Length);
//Handle Packet
PacketHandler.Packet(Encoding.UTF8.GetString(Packet));
//Makes _Buffer a new byte
_Buffer = new byte[1024];
//Get Ready to recive data
_Socket.BeginReceive(_Buffer, 0, _Buffer.Length, SocketFlags.None, RecivedCallBack, null);
}
Code that Handle
public static void Packet(string Message)
{
Console.WriteLine(Message);
switch (Message)
{
case "StartChat":
_ChatForm Start = new _ChatForm();
Start.ShowDialog();
break;
case "StopChat":
_ChatForm._Chat.EndChat();
break;
}
}
TCP is stream based, so your client has no way to know when the message has ended. Either use UDP, implement a way to detect the end of messages (eg send a 4 byte message with the length of the real message, before sending the real message... and read on the client until the whole message has been received), or use a library. I like Hazel: https://github.com/DarkRiftNetworking/Hazel-Networking.
The great thing about Hazel is that it implements reliable UDP. So, if you need to have your "messages" arrive in the order in which they were sent, or if you need guaranteed delivery and receipt of such messages (such as what TCP provides), then you can do so with their reliable UDP implementation.
They will also implement Web Sockets at some point :) Good luck!
A client/server example from the documentation:
Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using Hazel;
using Hazel.Tcp;
namespace HazelExample
{
class ServerExample
{
static ConnectionListener listener;
public static void Main(string[] args)
{
listener = new TcpConnectionListener(IPAddress.Any, 4296);
listener.NewConnection += NewConnectionHandler;
Console.WriteLine("Starting server!");
listener.Start();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
listener.Close();
}
static void NewConnectionHandler(object sender, NewConnectionEventArgs args)
{
Console.WriteLine("New connection from " + args.Connection.EndPoint.ToString();
args.Connection.DataReceived += DataReceivedHandler;
args.Recycle();
}
private static void DataReceivedHandler(object sender, DataEventArgs args)
{
Connection connection = (Connection)sender;
Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString());
connection.SendBytes(args.Bytes, args.SendOption);
args.Recycle();
}
}
}
Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hazel;
using Hazel.Tcp;
namespace HazelExample
{
class ClientExample
{
static Connection connection;
public static void Main(string[] args)
{
NetworkEndPoint endPoint = new NetworkEndPoint("127.0.0.1", 4296);
connection = new TcpConnection(endPoint);
connection.DataReceived += DataReceived;
Console.WriteLine("Connecting!");
connection.Connect();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
connection.Close();
}
}
}

C# Sockets: client is not connecting to server in seprate computers

Im new to c# sockets programing and im working on a little project of a server that sends strings for some clients. I made it by modifing MSDN's Synchronous Server and client Socket Example.
When I run the server and the clients on the same computer,they work fine, but when I run the server on a computer and the client on another computer, a socket exception shows on the client(both computers are at the same network).
Now im not sure what to do: port forwarding? change the code?
server code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace textweb
{
class Program
{
static int counter = 0;
static Socket[] _socket = new Socket[2];
static void Main(string[] args)
{
byte[] bytes = new Byte[1024];
//running the server on the local host
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
Console.WriteLine(ipHostInfo.HostName);
IPAddress ipAddress = ipHostInfo.AddressList[0];
Console.WriteLine(ipAddress);
TcpListener listener = new TcpListener(ipAddress, /*MyPort*/);
try
{
listener.Start(10);
Console.WriteLine("Waiting for a connection...");
while (counter < 2)
{
while (!listener.Pending()) { }
while (listener.Pending())
{
_socket[counter] = listener.AcceptSocket();
counter++;
}
}
bool _continue = true;
while (_continue)
{
string m = Console.ReadLine();
byte[] msg = Encoding.ASCII.GetBytes(m);
foreach (Socket soc in _socket)
{
soc.Send(msg);
if (m == "exit")
{
soc.Shutdown(SocketShutdown.Both);
soc.Close();
_continue = false;
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
}
}
}
client code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace textclient
{
class Program
{
static void Main(string[] args)
{
byte[] bytes = new byte[1024];
try {
IPHostEntry ipHostInfo = Dns.GetHostByName(/*server's ip*/);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress,/*MyPort*/);
Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
try {
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",sender.RemoteEndPoint.ToString());
bool _continue = true;
while (_continue)
{
if (sender.Available>0)
{
int bytesRec = sender.Receive(bytes);
string a = Encoding.ASCII.GetString(bytes, 0, bytesRec);
Console.WriteLine(a);
if (a == "exit")
{
sender.Shutdown(SocketShutdown.Both);
sender.Close();
_continue = false;
}
}
}
Console.ReadKey();
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
Console.ReadKey();
} catch (SocketException se) {
Console.WriteLine("SocketException : {0}", se.ToString());
Console.ReadKey();
} catch (Exception e) {
Console.WriteLine("Unexpected exception : {0}", e.ToString());
Console.ReadKey();
}
} catch (Exception e) {
Console.WriteLine( e.ToString());
Console.ReadKey();
}
}
}
}
I hope the question was clear and you will answer it,
Itay
Well, I found a solution very fast.
I just port-forwarded the port im using to the server ip.
for example if server ip is 10.0.0.1 and port is 2222
I just needed to forward port 2222 in with "lan users" 10.0.0.1.
Thank you for your help anyway.

Reset backlog after Socket server listen and response client

I am a newbie in C#, and I have developed a Socket program.
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
serverSocket.Listen(1);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
But after server response a client, server is closed and not listen any time. How should I do to reset server after calling Listen(backlog) to maintain server for a long time?
This is my code in ClientSide:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PC_Client
{
public partial class Form1 : Form
{
private static Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Form1()
{
InitializeComponent();
Console.ReadLine();
}
private void SendLoop()
{
string req = txtRequest.Text;
byte[] buffer = Encoding.ASCII.GetBytes(req);
clientSocket.Send(buffer);
byte[] receiveBuf = new byte[1024];
int rec = clientSocket.Receive(receiveBuf);
byte[] data = new byte[rec];
Array.Copy(receiveBuf, data, rec);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
}
private void LoopConnect()
{
int attempts = 0;
while(!clientSocket.Connected)
{
try
{
attempts++;
clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Console.WriteLine("Connection attempts: " + attempts.ToString());
}
}
//Console.Clear();
Console.WriteLine("Connected");
}
private void button1_Click(object sender, EventArgs e)
{
SendLoop();
}
}
}
I'm not sure about the particulars of C#, but in general, you want to wrap your accept call in a loop like so:
while(true) {
clientSocket = serverSocket.accept();
respond to socket in background thread
}
This way, your main thread will always be able to listen for sockets (because its wrapped in a while loop, and continues to accept new connections) while also not being blocked while handling a client request (because the client socket is handled in a background thread)

SocketException when connecting to server

I am running both client and server on the same machine.
Does any 1 know the error stated above?
server
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Net;
namespace Server
{
public partial class Server : Form
{
private Socket connection;
private Thread readThread;
private NetworkStream socketStream;
private BinaryWriter writer;
private BinaryReader reader;
//default constructor
public Server()
{
InitializeComponent();
//create a new thread from server
readThread = new Thread(new ThreadStart(RunServer));
readThread.Start();
}
protected void Server_Closing(object sender, CancelEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
//sends the text typed at the server to the client
protected void inputText_KeyDown(object sender, KeyEventArgs e)
{
// send the text to client
try
{
if (e.KeyCode == Keys.Enter && connection != null)
{
writer.Write("Server>>> " + inputText.Text);
displayText.Text +=
"\r\nSERVER>>> " + inputText.Text;
//if user at server enter terminate
//disconnect the connection to the client
if (inputText.Text == "TERMINATE")
connection.Close();
inputText.Clear();
}
}
catch (SocketException)
{
displayText.Text += "\nError writing object";
}
}//inputTextBox_KeyDown
// allow client to connect & display the text it sends
public void RunServer()
{
TcpListener listener;
int counter = 1;
//wait for a client connection & display the text client sends
try
{
//step 1: create TcpListener
IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
TcpListener tcplistener = new TcpListener(ipAddress, 9000);
//step 2: TcpListener waits for connection request
tcplistener.Start();
//step 3: establish connection upon client request
while (true)
{
displayText.Text = "waiting for connection\r\n";
// accept incoming connection
connection = tcplistener.AcceptSocket();
//create NetworkStream object associated with socket
socketStream = new NetworkStream(connection);
//create objects for transferring data across stream
writer = new BinaryWriter(socketStream);
reader = new BinaryReader(socketStream);
displayText.Text += "Connection " + counter + " received.\r\n ";
//inform client connection was successful
writer.Write("SERVER>>> Connection successful");
inputText.ReadOnly = false;
string theReply = "";
// step 4: read string data sent from client
do
{
try
{
//read the string sent to the server
theReply = reader.ReadString();
// display the message
displayText.Text += "\r\n" + theReply;
}
// handle the exception if error reading data
catch (Exception)
{
break;
}
} while (theReply != "CLIENT>>> TERMINATE" && connection.Connected);
displayText.Text +=
"\r\nUser terminated connection";
// step 5: close connection
inputText.ReadOnly = true;
writer.Close();
reader.Close();
socketStream.Close();
connection.Close();
++counter;
}
} //end try
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
}// end method runserver
}// end class server
client
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Net;
namespace Client
{
public partial class Client : Form
{
private NetworkStream output;
private BinaryWriter writer;
private BinaryReader reader;
private string message = "";
private Thread readThread;
//default constructor
public Client()
{
InitializeComponent();
readThread = new Thread(new ThreadStart(RunClient));
readThread.Start();
}
protected void Client_Closing(
object sender, CancelEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
//sends the text user typed to server
protected void inputText_KeyDown(
object sender, KeyEventArgs e)
{
try
{
if (e.KeyCode == Keys.Enter)
{
writer.Write("CLIENT>>> " + inputText.Text);
displayText.Text +=
"\r\nCLIENT>>> " + inputText.Text;
inputText.Clear();
}
}
catch (SocketException ioe)
{
displayText.Text += "\nError writing object";
}
}//end method inputText_KeyDown
//connect to server & display server-generated text
public void RunClient()
{
TcpClient client;
//instantiate TcpClient for sending data to server
try
{
displayText.Text += "Attempting connection\r\n";
//step1: create TcpClient for sending data to server
client = new TcpClient();
client.Connect("localhost", 9000);
//step2: get NetworkStream associated with TcpClient
output = client.GetStream();
//create objects for writing & reading across stream
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
displayText.Text += "\r\nGot I/O streams\r\n";
inputText.ReadOnly = false;
//loop until server terminate
do
{
//step3: processing phase
try
{
//read from server
message = reader.ReadString();
displayText.Text += "\r\n" + message;
}
//handle exception if error in reading server data
catch (Exception)
{
System.Environment.Exit(System.Environment.ExitCode);
}
} while (message != "SERVER>>> TERMINATE");
displayText.Text += "\r\nClosing connection.\r\n";
//step4: close connection
writer.Close();
reader.Close();
output.Close();
client.Close();
Application.Exit();
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
}
}
It is probably your firewall acting up. Try connecting to something like www.google.com on TCP 80 just to see if you can actually connect.
Are you using a newer version of Windows? It's possible that you're only listening on IPv4, but "localhost" is resolving to an IPv6 address and it's not finding it. Try connecting to "127.0.0.1" instead of localhost and see if the result changes.
mk,
I'd tcplistener/tcpclient for simple applications . . .
TheEruditeTroglodyte
If you use that constructor with TCPListener then it will let the underlying service provider pick a network address, which probably won't be 'localhost'. You're probably listening on your LAN/WLAN card instead of localhost.
Take a look at the MSDN page for TCPListener, the sample there shows how to use a different constructor, look at the other constructors for more samples.
Here's one way:
IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
TcpListener tcpListener = new TcpListener(ipAddress, 9000);

Categories