tag:blogger.com,1999:blog-62057464521839640942024-03-19T12:18:20.338+02:00Respected ProfessorSome, mostly techical, articles by Nikos FotiouΝίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-6205746452183964094.post-3948606889352821122023-04-04T23:36:00.001+03:002023-04-04T23:36:40.548+03:00Authenticate users in python scripts using their Google account<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWAL9_-npOSyVb7fcsdTq958CgeDBF6v5QOGDjfSqUMKr0oU9P9NW4ymHTR61mv2AN8tRcn7Slb3cWEDotSJu2y847UqieTchR2qVO1-VKZky6IR14gFJmyRq_wWYCzWCcMg37O-bw9WkGYYldl80jJU61c_PamYQP1TZFuYtUVCtcx2JpneKW8f_s8w/s1258/Screenshot%202023-04-04%20at%2011.13.49%20PM.png" style="display: block; margin-left: auto; margin-right: auto; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="928" data-original-width="1258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWAL9_-npOSyVb7fcsdTq958CgeDBF6v5QOGDjfSqUMKr0oU9P9NW4ymHTR61mv2AN8tRcn7Slb3cWEDotSJu2y847UqieTchR2qVO1-VKZky6IR14gFJmyRq_wWYCzWCcMg37O-bw9WkGYYldl80jJU61c_PamYQP1TZFuYtUVCtcx2JpneKW8f_s8w/s320/Screenshot%202023-04-04%20at%2011.13.49%20PM.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><br /></td></tr></tbody></table><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWAL9_-npOSyVb7fcsdTq958CgeDBF6v5QOGDjfSqUMKr0oU9P9NW4ymHTR61mv2AN8tRcn7Slb3cWEDotSJu2y847UqieTchR2qVO1-VKZky6IR14gFJmyRq_wWYCzWCcMg37O-bw9WkGYYldl80jJU61c_PamYQP1TZFuYtUVCtcx2JpneKW8f_s8w/s1258/Screenshot%202023-04-04%20at%2011.13.49%20PM.png" style="display: block; padding: 1em 0px; text-align: center;"></a></div>
<p>Google offers user authentication through OpenID Connect. Although usually, this feature is used by web sites, it can also be used with desktop applications. In <a href="https://github.com/controlthingsopensource/google-openidc" target="_blank">this repository</a> you can find a Python3 script that authenticates users based on their Google account. </p><p>What this script does is, it opens a web browser that redirects user to Google's authorization page and at the same time it begins a web server that "listens" for the <i>access code</i>. Upon receiving the access code it "exchanges" for an <i>id token</i> that includes user information.</p><p>Since the <i>client secret </i>of a desktop application can be easily protected, this script leverages <i>Proof Key for Code Exchange by OAuth Public Clients</i>, a technology defined in <a href="https://www.rfc-editor.org/rfc/rfc7636" target="_blank">RFC 7636</a> and supported by Google. With PKCE, the script generates a random <i>code verifier </i>and transmits its SHA-256 hash when requesting the access code. Then, it transmits the actual code verifier when requesting the id token. </p>Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-91102905104270995682023-03-28T12:36:00.001+03:002023-03-28T12:36:12.215+03:00A simple role-based access control system for .NET<p>In many cases, I need a simple solution for adding authentication and authorization in my .NET project, so as to easily develop the rest of the system. I need something simple, e.g., hardcode some user information in the configuration file. <a href="https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-7.0&tabs=visual-studio" target="_blank">ASP.NET Identity</a> is for most of the times an overkill. So I decided to create my own solution. You can find the source code of my solution in this <a href="https://github.com/controlthingsopensource/SimpleRBAC" target="_blank">GitHub repository</a>. </p><p>The most important part is in the <a href="http://appsettings.Development.json" target="_blank">appsettings.Development.json</a> file where users, their passwords, and their roles are defined. For example:</p>
<pre><code>
"AuthorizedUsers": {
"administrator": {
"Password": "admin!",
"Roles": [ "Administrator" ]
},
"user1": {
"Password": "user1!",
"Roles": [ "User" ]
}
}
</code></pre>
<p>Then, in the <a href="https://github.com/controlthingsopensource/SimpleRBAC/blob/master/SimpleRBAC/Program.cs" target="_blank">Program.cs</a> file the following code must be added:</p>
<pre><code>
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
});
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
...
app.UseAuthentication();
app.UseAuthorization();
</code></pre>
<p>
User authentication is handled by the <a href="https://github.com/controlthingsopensource/SimpleRBAC/blob/master/SimpleRBAC/Controllers/AccountController.cs" target="_blank">Account </a>controller. By default all pages are accessed only by authenticated users. If you want to restrict a page to particular role a decorator can be added to the corresponding controller method, e.g.:</p>
<pre><code>
[Authorize(Roles = "Administrator")]
public IActionResult Admin()
{
return View();
}
</code></pre>
<p>I hope you can find this code useful</p>Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-23953829095490026852022-04-06T21:13:00.001+03:002022-04-06T21:13:41.623+03:00Make fun things with your home IoT devices, securely over the internet. <p>I am planning to start a series of posts discussing how to put your IoT devices in the internet and do fun stuff with them. I will provide them as GitHub Wiki pages and I will also provide code and scripts when this is possible. This page will act as a placeholder.</p><h2 style="text-align: left;">Interact using Alexa with your IoT devices</h2><div><a href="https://github.com/controlthingsopensource/alexa-iot/wiki" target="_blank">In this first post</a> I am using the excellent, free, Cloudflare Tunnel and I make my Raspberry Pi accessible over the internet using a custom domain and HTTPS. Only with a few clicks and no cost (apart from the cost of the domain name).</div><div><br /></div><div>Then I provide an Amazon Alexa Skill that can be used for interacting with your Raspberry Pi using your Alexa device! In this simple example, I am implementing a simple REST API which is invoked using voice commands.</div><div><br /></div><div>Have fun!</div><p><br /></p>Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-38015021777750388012020-08-10T22:31:00.002+03:002020-08-10T22:31:38.024+03:00Create a JWT singed with RSA private key in .net core<p>The following example is a snippet of a C# code that generates an RSA private key out of a .pem file and uses it to sign a JWT. The privateKey variable, stores the contents of the .pem file minus the "-----BEGIN RSA PRIVATE KEY----" and "-----END RSA PRIVATE KEY-----" lines.</p>
<pre>
string privateKey = @"
MIIEpAIBAA
...
y53DdfYA==";
byte[] RSAprivateKey = Convert.FromBase64String(privateKey);
RSA rsa = RSA.Create();
rsa.ImportRSAPrivateKey(RSAprivateKey, out _);
var jwt = tokenHandler.CreateEncodedJwt(
issuer: "...",
audience: ...,
...
signingCredentials: new SigningCredentials(
key: new RsaSecurityKey(rsa),
algorithm: SecurityAlgorithms.RsaSha256)
);
</pre>Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-43233718396733522342020-04-09T23:04:00.002+03:002020-06-03T01:11:27.297+03:00Deploying smart contracts to ganache using python and web3<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://www.trufflesuite.com/ganache">Ganache</a> is a useful tool that emulates Ethereum blockchain in your local machine and it is very practical for testing smart contracts. Most tutorials explain how to deploy a smart contract in ganache using <a href="https://www.trufflesuite.com/truffle">truffle</a>, which is a development framework by the same company. But this is not necessary. Here, I explain how to write and compile a contract using <a href="https://remix.ethereum.org/">Remix</a>, and deploy it using python and web3.py.<br />
<br />
Write your smart contract in remix and compile it. Then press the "ABI" button on the bottom left (see picture) and paste the output in a file. This will be our ABI_file. Do the same with the "Bytecode" bottom. This will be the bin_file. Then you can use the python script from this <a href="https://github.com/nikosft/ganache-remix">github repository</a>. Make sure you have installed the dependencies and that you have modified the ABI_file and bin_file variables of the script accordingly.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo3oH_U_ktDafnWDvcmEa6qPyIQCIWCoRofjwwkZdaXuZZ3yBEjPi8-uGiH8xQlPASKLCPDqyWHcSJvyyiitqwoeumc0a9o0faX5VIkkt0QwA3KRCMlx4mkZ2-mKhRKnkSLOOenldtXA5I/s1600/remix.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="699" data-original-width="793" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo3oH_U_ktDafnWDvcmEa6qPyIQCIWCoRofjwwkZdaXuZZ3yBEjPi8-uGiH8xQlPASKLCPDqyWHcSJvyyiitqwoeumc0a9o0faX5VIkkt0QwA3KRCMlx4mkZ2-mKhRKnkSLOOenldtXA5I/s320/remix.png" width="320" /></a></div>
<br />
<br />
<br /></div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-85907507162098355662019-05-19T23:51:00.003+03:002019-05-19T23:51:58.685+03:00CoAP POST using libcoap<div dir="ltr" style="text-align: left;" trbidi="on">
<b><a href="https://respected-professor.blogspot.gr/2016/07/libcoap-examples.html">View a list of all libcoap examples here</a></b>.<br />
<br />
<span style="background-color: white; caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">This example includes a CoAP server and a CoAP client. </span><br style="caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" /><span style="background-color: white; caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">The client performs a CoAP POST request for the "coap://127.0.0.1/hello" resource. </span><span style="background-color: white; caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">The server listens on port 5683 (default port) and prints the POSTed data</span><br style="caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" /><br style="caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" /><span style="background-color: white; caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">You can find the source code of this example, as well as, instructions for compiling it in Linux in this </span><a href="https://github.com/nikosft/libcoap" style="color: #4d469c; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; text-decoration: none;">github repository</a><span style="background-color: white; caret-color: rgb(68, 68, 68); color: #444444; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">, in the "post" folder.</span></div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-79719550231396926232016-11-25T15:03:00.001+02:002016-11-25T15:53:00.398+02:00A CoAP server for the riot operating system using libcoap<div dir="ltr" style="text-align: left;" trbidi="on">
<b><a href="https://respected-professor.blogspot.gr/2016/07/libcoap-examples.html">View a list of all libcoap examples here</a></b>.<br />
<br />
The riot operating system (<a href="https://riot-os.org/">https://riot-os.org/</a>) is an operating system for the Internet of Things that currently supports <a href="https://riot-os.org/#usage">many platforms</a>. One of the main advantages of riot is that it supports programs and libraries written in C including libcoap.<br />
<br />
In this github repository you will find an example of a CoAP server for the riot operating system https://github.com/nikosft/libcoap/tree/master/riot This server implements a default resource that outputs "Hello World!".In order to test the example, download the latest version of the rios os (<a href="https://github.com/RIOT-OS/RIOT">https://github.com/RIOT-OS/RIOT</a>), create a folder inside the examples directory and copy the code from <a href="https://github.com/nikosft/libcoap/tree/master/riot">https://github.com/nikosft/libcoap/tree/master/rio</a>t in that new directory. Then from a terminal type<br />
$ make<br />
<br />
If you encounter any problem, consult this riot wiki page <a href="https://github.com/RIOT-OS/RIOT/wiki/Family:-native">https://github.com/RIOT-OS/RIOT/wiki/Family:-native</a> In order to use the example you have to create a virtual interface in your linux machine. In order to do this invoke the following utility:<br />
$ <riot directory>/dist/tools/tapsetup/tapsetup -c1<br />
<br />
This utility will create a virtural interface and a bridge (for more information visit this wiki page <a href="https://github.com/RIOT-OS/RIOT/wiki/Virtual-riot-network">https://github.com/RIOT-OS/RIOT/wiki/Virtual-riot-network</a>). After this step, from the folder where you have put the example code invoke:<br />
$ make term<br />
<br />
This command will execute the binary created in the previous step and soon an ipv6 address will appear in the terminal. You can now access the coap server using the libcoap coap client and the displayed ipv6 address, by invoking the following command:<br />
$ coap-client coap://[<ipv6 address>%tapbr0]<br />
<br /></div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-19585381659759341512016-09-06T14:40:00.000+03:002016-09-06T14:41:09.723+03:00Asynchronous CoAP request-response using libcoap<div dir="ltr" style="text-align: left;" trbidi="on">
<b><a href="https://respected-professor.blogspot.gr/2016/07/libcoap-examples.html">View a list of all libcoap examples here</a></b>.<br />
<br />
This is an example of asynchronous request-response. The server
listens on port 5683 (default port). When it receives a request for the "hello" resource, it sends and ACK and after 2 seconds it responds with a "Hello World!".
<br />
<br />
The client performs a CoAP GET request for the "coap://127.0.0.1/hello" resource and prints the response.<br />
<br />
You can find the source code of this example, as well as, instructions for compiling it in Linux in this <a href="https://github.com/nikosft/libcoap">github repository</a>, in the "seperate" folder.</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-73994122566974204282016-07-17T00:06:00.001+03:002019-05-19T23:52:42.484+03:00libcoap examples<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://libcoap.net/">libcoap</a> is an open source C implementation of the <a href="https://tools.ietf.org/html/rfc7252">CoAP protocol</a>. It can be used for developing CoAP services in Linux, MacOS, as well as, in various IoT operating systems such as Contiki, LwIP, and TinyOS.<br />
<br />
However, libcoap lacks documentation. Apart from some installation instructions there is not any tutorial on how to use the library. Moreover, the examples included in the source code are very complex and they cause confusion. I have constructed a small set of examples that use libcoap to perform simple tasks.<br />
<br />
All examples are available on <a href="https://github.com/nikosft/libcoap">github</a><br />
<h3 style="text-align: left;">
List of examples</h3>
<ul style="text-align: left;">
<li><a href="https://respected-professor.blogspot.gr/2015/11/a-hello-world-coap-server-using-libcoap.html">A simple hello world client-server</a></li>
<li><a href="https://respected-professor.blogspot.gr/2016/09/asynchronous-coap-request-response.html">Asynchronous request-responses</a> </li>
<li><a href="https://respected-professor.blogspot.gr/2016/11/a-coap-server-for-riot-operating-system.html">Uisng libcoap with the riot operating system</a> </li>
<li><a href="https://respected-professor.blogspot.com/2019/05/coap-post-using-libcoap.html">COAP POST requests</a></li>
</ul>
<br />
<br />
<br /></div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-43513392539543100052016-03-29T10:32:00.001+03:002016-03-29T10:32:56.707+03:00Share a host folder with an Ubuntu VM using VirtualBox<div dir="ltr" style="text-align: left;" trbidi="on">
This post describes how an Ubuntu based virtual machine on VirtualBox can access a windows folder.<br />
<br />
In order to achieve this functionality follow the next steps.<br />
<br />
Step 1. Run VirtualBox Manager, right click on your VM and select settings. There select the "Shared Folders" Option and press the add button on the right. In the "Folder Path" select the folder that you want to share, and in the "Folder Name" type a name. Moreover, select "Auto-mount" and "Make Permanent".<br />
<br />
<img alt="" src="data:image/png;base64,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" /><br />
<br />
Step 2. Run your VM. Your folder has been mounted in the directory /media named "sf_<Folder Name>", where <Folder Name> is the name you selected in step 1. Nevertheless, this folder cannot be accessed.<br />
<br />
Step 3. In order to be able to access the shared folder from your VM you have to add you user account to the group "vboxsf". You can do that by executing the following command:<br />
<br />
<div style="text-align: center;">
<code>sudo usermod -a -G vboxsf <username> </code></div>
<br />
Where <username> is your account user name. Restart, and you will be able to access the shared folder. </div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-176044104941089492015-11-24T17:28:00.000+02:002016-09-06T14:42:19.692+03:00A Hello World CoAP client-server using libcoap<div dir="ltr" style="text-align: left;" trbidi="on">
<b><a href="https://respected-professor.blogspot.gr/2016/07/libcoap-examples.html">View a list of all libcoap examples here</a></b>.<br />
<br />
This is a simple example of a CoAP server and a CoAP client. The server listens on port 5683 (default port) and responds with a "Hello World!" to every request for the "hello" resource. The response is piggybacked in the ACK message.<br />
<br />
The client performs a CoAP GET request for the "coap://127.0.0.1/hello" resource and prints the response.<br />
<br />
You can find the source code of this example, as well as, instructions for compiling it in Linux in this <a href="https://github.com/nikosft/libcoap">github repository</a>, in the "piggybacked" folder.</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-36020117064254305092015-10-21T14:04:00.001+03:002015-10-21T14:12:04.560+03:00DLNA with subtitles in D-Link DNS-320 <div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1xxQu-1mNyv-ST_ejo5cHx3T3B1Ewe-yzzkZFVvl0hKlgiyziJaZH4dNuC8QmWxNRBvoe06_yvQ60TGgG3C7l4Is8jEmFQG0xcG5GaHQBEyPaT_LEladWdkbqz1xWxLVWq_5fA09E7-0T/s1600/DNS_320L_angle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1xxQu-1mNyv-ST_ejo5cHx3T3B1Ewe-yzzkZFVvl0hKlgiyziJaZH4dNuC8QmWxNRBvoe06_yvQ60TGgG3C7l4Is8jEmFQG0xcG5GaHQBEyPaT_LEladWdkbqz1xWxLVWq_5fA09E7-0T/s320/DNS_320L_angle.png" width="320" /></a></div>
<br />
D-Link DNS-320 is a network storage enclosure that supports DLNA. Unfortunately, the built-in DLNA server does not support subtitles. Nevertheless, this can be overcome by installing miniDLNA. miniDLNA can stream movies and subtitles, providing that the subtitles file has the same name as the movie file (minus the extension). The following has been tested successfully with UTF-8 encoded .srt files in Samsung UE46ES6340 smart tv.<br />
<br />
DNS-320 is a linux based device. Moreover, it's firmware can execute scripts, located in the root directory, every time the system boots. Fonz fun plug (ffp), its such a script that adds support for telnet, as well as, for installing additional software. In this post, we will use ffp ton install miniDLNA in our NAS.<br />
<h3 style="text-align: left;">
</h3>
<h3 style="text-align: left;">
<br /></h3>
<h3 style="text-align: left;">
Step 0 preparation</h3>
Make sure you have disabled the built-in DLNA server<br />
<h3 style="text-align: left;">
</h3>
<h3 style="text-align: left;">
<br /></h3>
<h3 style="text-align: left;">
Step 1 install ffp</h3>
Installing ffp is as trivial as copy pasting a file. Follow the instructions here <a href="https://nas-tweaks.net/371/hdd-installation-of-the-fun_plug-0-7-on-nas-devices/">https://nas-tweaks.net/371/hdd-installation-of-the-fun_plug-0-7-on-nas-devices/</a><br />
<h3 style="text-align: left;">
</h3>
<h3 style="text-align: left;">
<br /></h3>
<h3 style="text-align: left;">
Step 2 install miniDLNA</h3>
The web page included in step 2 has instructions about how to connect to your NAS using telnet. Follow these instructions and connect to your NAS. ffp includes a package manager for installing software. Initially, the package manages has to be configured with download sites. This can be done using uwsiteloader. uwsiteloader can be installed by following the instructions here <a href="https://nas-tweaks.net/371/hdd-installation-of-the-fun_plug-0-7-on-nas-devices/#Now_what.3F">https://nas-tweaks.net/371/hdd-installation-of-the-fun_plug-0-7-on-nas-devices/#Now_what.3F</a> After downloading it and making it executable, run it. In the step when it requests to select download sites, select all of them. You can then install miniDLNA and configure following the steps here: <a href="http://forum.nas-central.org/viewtopic.php?f=249&t=5841&start=45#p56567">http://forum.nas-central.org/viewtopic.php?f=249&t=5841&start=45#p56567</a> section "INSTALL INSTRUCTIONS". Make sure you edit /ffp/etc/minidlna.conf accordingly (vi can be used for the editing).<br />
<br />
You are ready to go! A useful command that forces miniDLNA to rebuilt its database is /ffp/start/minidlna.sh rescan<br />
<br />
<br /></div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-74407239379311525102015-07-28T16:47:00.000+03:002015-07-28T16:47:37.197+03:00Create self-singed certificate with extentions<div dir="ltr" style="text-align: left;" trbidi="on">
For testing reasons I wanted to create a self-signed certificate that includes the subject alternative name extension, using openssl. Most guides require the creation of an openssl configuration file. I found out that this can be done without any configuration file, using only two openssl commands and a file that contains the subject alternative name extension parameters.<br />
<br />
The first command is the following:<br />
<br />
<code>
openssl req -newkey rsa:1024 -keyout server.key -out server.csr -subj '/C=GR/ST=Attiki/L=Athens/O=Fotiou Corp/OU=Security Department/CN=localhost/emailAddress=my@email.address' -nodes
</code>
<br />
<br />
This command creates a new private key and a new certificate signing request. Let's see the command parameters:<br />
<br />
<code>-newkey rsa:1024</code> It creates an RSA 1024 bits key<br />
<code>-keyout server.key</code> This is the file where the private key is stored<br />
<code>-out server.csr</code> This the file where the certificate signing request is stored<br />
<code> -subj ... </code> This is the information included in the certificate<br />
<code>-nodes</code> This command parameter instructs openssl to not encrypt the private key
<br />
<br />
Now create a file and insert the <a href="https://www.openssl.org/docs/apps/x509v3_config.html#Subject-Alternative-Name">subject alternative name extension parameters</a>. In this example, I have created a file named <code>extentions.cnf</code> which contains the following text:<br />
<br />
<code>subjectAltName=DNS:example.com, DNS:localhost</code><br />
<br />
This line indicates that this certificate is valid for two DNS names, namely example.com and localhost. You may notice that the CN name included in the -subj command line parameter is also included here; the reason for that is because most browsers ignore the CN field when the subject alternative name extension is used. Finally the following command creates the desired certificate<br />
<br />
<code>openssl x509 -req -days 365 -signkey server.key -in server.csr -out server.crt -extfile extentions.cnf</code><br />
<br />
<br />
Where:<br />
<code>-days 3650</code> It is the number of days for which the certificate is valid<br />
<code>-signkey server.key</code> It is the private key generated previously and it used to sign the certificate<br />
<code>-in server.csr</code> The certificate signing request we created with the previous command<br />
<code>-out server.crt</code> The file in which the certificate will be stored<br />
<code>-extfile extentions.cnf</code> The file we created with the subject alternative name extension parameters
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-46357039182611598762014-10-20T01:00:00.000+03:002014-10-20T01:00:08.453+03:00Handling C#, MVC entity validation errors in a meaningful way<div dir="ltr" style="text-align: left;" trbidi="on">
MVC's entity framework is a convenient tool for abstracting databases. However, when something goes wrong the debug messages are not very meaningful. Especially when an entity validation exception occurs.<br />
<br />
The following try, catch block catches an entity validation exception and concatenates all validation error messages into a single string. Then this string can be displayed in a debug message.<br />
<br />
<pre><code>
try
{
entities.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
var errorMessages = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage);
//Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
throw new Exception(fullErrorMessage);
}
</code>
</pre>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-3566811353569822342013-10-14T21:18:00.001+03:002013-10-14T22:44:57.591+03:00The unfortunate cookies<div dir="ltr" style="text-align: left;" trbidi="on">
<h3>
Cookies sent over plain HTTP to Google websites can reveal information about a user</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuTKi2IIlh0WdopCxmPYHdl8Nb-qyZJM-Tp9a0rJGY5L9KH54PJ7jWjX7fay_fidf40DRbquMbFFXSg3NCufPLOy_miuD5URHjEw4H0rJxh1JJ2F3psWiz-vA5Ve2XIlvD2-ZQsxFxhwbr/s1600/fortune_cookie.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuTKi2IIlh0WdopCxmPYHdl8Nb-qyZJM-Tp9a0rJGY5L9KH54PJ7jWjX7fay_fidf40DRbquMbFFXSg3NCufPLOy_miuD5URHjEw4H0rJxh1JJ2F3psWiz-vA5Ve2XIlvD2-ZQsxFxhwbr/s1600/fortune_cookie.jpg" /></a></div>
<div>
<br /></div>
<div>
<u>Disclaimer</u></div>
<div>
The following has been reported to Google and is considered <b><u>not an issue</u></b></div>
<div>
<b><u><br /></u></b></div>
<div>
Recently while visiting Google scholar I noticed that on the top right corner my Google username was displayed.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTNuwxU1hS3Yr2bhs-KJjp0dD-8E6qq9_HkSiRlvUzvwGCSnR1x7JtCGSSBaskVviuGxZ9jxjgzEoenDFBrzqRoiQpSh5vF2iIgpKBZ6wbRIJilm7Z1BUoxsHZTrm7pjp0siLH-bEPnAG1/s1600/scholar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="189" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTNuwxU1hS3Yr2bhs-KJjp0dD-8E6qq9_HkSiRlvUzvwGCSnR1x7JtCGSSBaskVviuGxZ9jxjgzEoenDFBrzqRoiQpSh5vF2iIgpKBZ6wbRIJilm7Z1BUoxsHZTrm7pjp0siLH-bEPnAG1/s320/scholar.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
This appeared to me very strange, since I was not accessing this service using HTTPs. I fired up Wireshark and I revisited scholar once again. From the captured traffic it was obvious that my browser was sending a bunch of cookies over plain HTTP. I stored these cookies to a file, I imported them to a Firefox private browsing window and I visited Google scholar once again. To my surprise my username was still there. Moreover I was able to see my citations and my updates just like if I was signed in. By observing the cookies I noticed that most of them were for the domain *.google.gr, so as next step I visited http://www.google.gr/ig in the same private session: all gadgets that do not require authentication (like weather) were there!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
But the surprises continued. I edited the cookies file and I replaced the domain *.google.gr with *.youtube.com, I loaded the new file in a new Firefox private browsing window and I visited http://www.youtube.com. As it can be observed from the screenshot, my username, my subscriptions, as well as posts of my friends in google+, all were there!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPHdlLzSXeE-9tAmpa38PWkzbvX_74q5hj9IaNt49las5AWosiejFcv2PCfqNHm3NcQJoKCzeV55cYnc-WelQ2HS7cXTlnidwo_Sn6DQhpIcb4IhMG_UizmLtMCLghmE3ISVcZc4ZQOLeA/s1600/youtube.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPHdlLzSXeE-9tAmpa38PWkzbvX_74q5hj9IaNt49las5AWosiejFcv2PCfqNHm3NcQJoKCzeV55cYnc-WelQ2HS7cXTlnidwo_Sn6DQhpIcb4IhMG_UizmLtMCLghmE3ISVcZc4ZQOLeA/s320/youtube.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
It is astonishing how much information about a user can be gained simple by monitoring a mere HTTP session. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Edit 1:</div>
<div class="separator" style="clear: both; text-align: left;">
Even if the user logs out, the captured cookies continue to reveal the same information</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-76061705611214849462013-08-12T20:23:00.001+03:002013-08-13T00:59:37.555+03:00Convert video files and embed subtitles using VLC<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://www.videolan.org/vlc/">VLC</a> player, by VideoLAN, is a handy media player with many features. VLC, among other things, enables the conversion of video files, from one format to another, enabling the same time the incorporation of subtitles.<br />
<br />
Suppose that we want to convert an h.254 video file to DivX with embedded subtitles. Suppose also that subtitles are stored in a separate (.srt) file with <b>the same name as the video file</b>. Here are the steps that should be followed:<br />
<br />
Run VLC and from the <i>Media</i> menu, select <i>Convert/Save (Ctrl + R)</i>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigPXKA3lydtI58HJ7NK4ieVTH4q_GffGsJSwUy9N0CCuwJF4sITMfcuyrSUfmTSJd2581gzoTK2VawebIy1TOZBu9vj6L-Tc8Rrw3FcAPP0tIVWDHe1KWbVeRTYcg-GEIz_6SunWm7bB84/s1600/step-1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigPXKA3lydtI58HJ7NK4ieVTH4q_GffGsJSwUy9N0CCuwJF4sITMfcuyrSUfmTSJd2581gzoTK2VawebIy1TOZBu9vj6L-Tc8Rrw3FcAPP0tIVWDHe1KWbVeRTYcg-GEIz_6SunWm7bB84/s320/step-1.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Select Convert/Save</td></tr>
</tbody></table>
<br />
In the <i>file selection</i> area, press <i>Add</i>, and choose the video file to be converted. Moreover, on the button-left menu press the arrow and select <i>Convert</i>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeOGtBkHiDSXDXV0Um5eFo7I_UdXcmpnH6DiOm1EOSF40yYvlaRZVg-uiLRPtB1fYs3Z-_iLNs2UO9eBp6Wi2XVRpQDVqbRw67SQ82aP41e5SMrOi7iSTn_nB5-bl2A6Bq-bQngjQB4V_C/s1600/step-2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeOGtBkHiDSXDXV0Um5eFo7I_UdXcmpnH6DiOm1EOSF40yYvlaRZVg-uiLRPtB1fYs3Z-_iLNs2UO9eBp6Wi2XVRpQDVqbRw67SQ82aP41e5SMrOi7iSTn_nB5-bl2A6Bq-bQngjQB4V_C/s320/step-2.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Select the Convert optionn</td></tr>
</tbody></table>
<br />
In the <i>Destination</i> area, press <i>Browse</i>, and select where your file should be saved (Note that you have to add the filename as well the extension). In the <i>Settings</i> area, select the Convertion <i>profile</i> and press the <i>Edit selected profile</i> button.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBG0GGkDodaZ7arAVjD6bSI4SX_RHSOqvOqpHZekpbsek51Tw10A08i-x1fSpiXyo-QmRVF4W15sBDZfHely-6Piq4Q-EcS3DIq4PnuW35Z1hVgaHquoMkO8RY1tQhcEKSQpZ2JMECiY_A/s1600/step-3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBG0GGkDodaZ7arAVjD6bSI4SX_RHSOqvOqpHZekpbsek51Tw10A08i-x1fSpiXyo-QmRVF4W15sBDZfHely-6Piq4Q-EcS3DIq4PnuW35Z1hVgaHquoMkO8RY1tQhcEKSQpZ2JMECiY_A/s320/step-3.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Press the button marked with the black square</td></tr>
</tbody></table>
<br />
In the new window select the <i>Subtitles</i> tab, check the <i>Subtitles</i> check box, select <i>DVB subtitle </i>on the listbox on the left, and check the <i>Overlay subtitles on the video </i>check box. Then press <i>Save</i>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg__4uSZ6oZIZNILUks4iMp8hpGccz9_XEyvUQcver621pqyeZrNk7mEdTNYvRhxWOWEKvCu2jKabe3qF3LM5Ei_tOeiytR-p-VL_x7kRQdgGlwD-Lq4nHw7u1QMHe2gDhikvtDZhWsMPVV/s1600/step-4.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="308" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg__4uSZ6oZIZNILUks4iMp8hpGccz9_XEyvUQcver621pqyeZrNk7mEdTNYvRhxWOWEKvCu2jKabe3qF3LM5Ei_tOeiytR-p-VL_x7kRQdgGlwD-Lq4nHw7u1QMHe2gDhikvtDZhWsMPVV/s320/step-4.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Subtitle options</td></tr>
</tbody></table>
<br />
Now by pressing <i>Start</i>, your video will be converted to desired format and the subtitles will be embedded in the output video file. </div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-71552368364270851852012-09-01T13:28:00.000+03:002015-03-03T16:02:58.038+02:00Send a facebook message using php<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://developers.facebook.com/docs/reference/apis/">Facebook API</a> does not provide any method for sending a message to the inbox of a user. Fortunately, messages can also be sent using XMPP, which is used by facebook chat, but can also be used for sending a message to a user that is offline (i.e., the message will appear in the user's inbox).<br />
<br />
In this <a href="https://github.com/nikosft/FB-Message">link</a> you can find a php class that utilizes facebook's XMPP functionality and sends a message to a facebook user.<br />
<br />
In order to use this class you need to obtain an API key, by registering your application <a href="https://developers.facebook.com/apps">here</a>.
In order to use this class you should provide, your API key, your user id, the current authorization token, and the user id of the user to which you wish to send a message.<br />
<br />
In order to get your user id, you can user the facebook <a href="https://developers.facebook.com/docs/reference/php/">php sdk</a> and use the getUser() method of the Facebook class.
In order to get the authorization token you can invoke the getAccessToken() of the Facebook class</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-81238889883779608262012-08-01T13:22:00.000+03:002014-06-04T16:38:42.447+03:00A proxy re-encryption implementation<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://en.wikipedia.org/wiki/Proxy_re-encryption">Proxy re-encryption</a> is scheme that allows a proxy to re-encrypt a ciphertext, encrypted with the public key of a user A, into a ciphertext that can be decrypted with a private key of a user B, without having access to the private key of A or B, as well as to the plaintext.<br />
<br />
Green and Ateniese describe an Identity-based proxy re-encryption scheme <a href="http://link.springer.com/chapter/10.1007%2F978-3-540-72738-5_19?LI=true">in their paper</a> and prove its security. An implementation of their solution can be found in my <a href="https://github.com/nikosft/IB-PRE"> github repository</a>. This is a python implementation using the <a href="http://www.charm-crypto.com/"> Charm Crypto tool</a>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-6852079703626117682012-07-01T13:20:00.000+03:002013-03-29T13:21:10.443+02:00Export excel diagrams to pdf and use them in latexIf you are creating your diagrams using Excel 2007, there is an easy way to export them in .pdf and then use them as figures in your latex documents.<br />
<br />
Open your excel document, select your diagram and then press the office logo and select save as->pdf or exps. Choose a file name and select save as file type tou be PDF (*.pdf). This will result in a pdf file with the diagram and a lot of blank space. In order to remove the blank space use pdfcrop. This a utility is included both in MikTex (latex for windows) as well as in texlive-extra-utils ubuntu package. Alternatevily you can download it from <a href="http://pdfcrop.sourceforge.net/">here</a>Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-265401348925321292012-06-01T13:17:00.000+03:002013-03-29T13:18:38.088+02:00Running an IIS7 site from a network driveRunning a web site, located in a network share, in IIS7 can be really tricky, as it usually ends up with IIS7 complaining about permission problem. This usually happens because IIS processes run as a different user, who is not allowed to access network shares. In this blog post it is shown how a web site can be run in the context of a user that is eligible to access a network share.<br />
<br />
But before we start an important note: Running a web site in the context of a privileged user may possibly entail security risks.<br />
<br />
In this blog post the following setup is considered: a network drive with IP 192.168.2.6 and share called fotiou, which is password-protected. The share has been mapped, by user User_NAME, to a network drive (Z:), windows have been configured to connect to that drive on start up, and our web site is located in Z:\wordpress.<br />
<br />
From the IIS7 manager console add a new web site. In our case the site is named wordpress. In the Physical path textbox insert the full URI to the website and not the mapped drive (in our case this would be \\192.168.2.6\fotiou\wordpress), and press OK.<br />
<br />
Now navigate in the Application Pools located above the Sites option (see the picture below)<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz0UszoJMMM4pbY4PSRcxhxJ79oWyx9I3GkpK8WV3qYMyMUM05ezD2P2zxIuGTVOUVw71GkwlJULFfRhpJ9wkBVObpC9dulyszZm35eXGnqHBIsKFpiamz2TtgZxXsODdaJFQflqA7-J7W/s1600/img1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz0UszoJMMM4pbY4PSRcxhxJ79oWyx9I3GkpK8WV3qYMyMUM05ezD2P2zxIuGTVOUVw71GkwlJULFfRhpJ9wkBVObpC9dulyszZm35eXGnqHBIsKFpiamz2TtgZxXsODdaJFQflqA7-J7W/s320/img1.png" width="320" /></a></div>
<br />
From the Application Pools list select the newly created site (named wordpress in our example, as depicted below)<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYVpPKJuN3Nw7wqTsboKvQLUynG4uROMSXZoU5FIOXfTVOmScNa5SjoaYXk6UVXoPc-6riqNhRttQ727dWrXqg7MUqdtaPCLscIDP2K9sKwEH-OxpCqAXVcGLK7QGfrorRvbZRUPT7PjUb/s1600/img2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYVpPKJuN3Nw7wqTsboKvQLUynG4uROMSXZoU5FIOXfTVOmScNa5SjoaYXk6UVXoPc-6riqNhRttQ727dWrXqg7MUqdtaPCLscIDP2K9sKwEH-OxpCqAXVcGLK7QGfrorRvbZRUPT7PjUb/s320/img2.png" width="320" /></a></div>
<br />
Right click and select Advanced Settings. The in the Process Model tab, edit the Identity option, by selecting the Custom account option, and by setting it to the current user, as in the picture below<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB1kvR4KY4J0063RYw65TAjv0kv0eXUgeXV4m6IKu8XhJgvZoayAJTXfHacwdQGvIyL-U69_2UcxEIIqJOQkjMH0cfZi8-0W905WZbgoi5_Wtk7Gj3nZTUj6VZ09NI0fxG_50WZ8swbE1h/s1600/img3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB1kvR4KY4J0063RYw65TAjv0kv0eXUgeXV4m6IKu8XhJgvZoayAJTXfHacwdQGvIyL-U69_2UcxEIIqJOQkjMH0cfZi8-0W905WZbgoi5_Wtk7Gj3nZTUj6VZ09NI0fxG_50WZ8swbE1h/s320/img3.png" width="228" /></a></div>
<br />
<br />
Now navigate back to the Sites tree, select your web site and double click the Authentication option<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipflNwv_Q3T5Gj1Xg1aYhtlq1pBbODWXGD1ER6j6fpSaTUSSGUOxNzHNhmr1VsjvniyYAFQ0Ty_KZTu_D1zYPuRUGoW0C5SQyg3V2krRrd5wjOgF-QJxbSckzA9qeD-XZsRXDXwtJMqP76/s1600/img4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipflNwv_Q3T5Gj1Xg1aYhtlq1pBbODWXGD1ER6j6fpSaTUSSGUOxNzHNhmr1VsjvniyYAFQ0Ty_KZTu_D1zYPuRUGoW0C5SQyg3V2krRrd5wjOgF-QJxbSckzA9qeD-XZsRXDXwtJMqP76/s320/img4.png" width="267" /></a></div>
<br />
Double click on the Anonymous Authentication option and select Application pool identity<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgbLxnpJqAoL95xjata826eoqEYyc8gBFzGDVHshH8NqB0bCblTqNCNyMAvAlF3iJ2NxZOxYGl71FtII6ZYzdl5GtBS3V80MphuwKnrXSawNVqPxDIDHZ-EWo2WZJRndMhYHDD_pPA6gSh/s1600/img5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgbLxnpJqAoL95xjata826eoqEYyc8gBFzGDVHshH8NqB0bCblTqNCNyMAvAlF3iJ2NxZOxYGl71FtII6ZYzdl5GtBS3V80MphuwKnrXSawNVqPxDIDHZ-EWo2WZJRndMhYHDD_pPA6gSh/s320/img5.png" width="320" /></a></div>
<br />
Now your web site can be run without permission problems.Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-66044337821757856582012-05-01T13:07:00.000+03:002013-03-29T13:09:46.567+02:00Handle Geek characters in an Access database with JavaWhen reading Greek characters from an access database special action needs to be taken in order to properly display them.
The following code prints two string fields named <i>name </i>and <i>surname</i>, stored in an access database:
<br />
<br />
<div class="source_code">
<code>
<pre>
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String filename = "THE_MDB_FILE";
String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=";
database += filename.trim() + ";DriverID=22;READONLY=true;useUnicode=true}";
dbConnection = DriverManager.getConnection(database);
Statement s = dbConnection.createStatement();
String query = "Select * from Users";
ResultSet rs = s.executeQuery(query);
String name = new String(rs.getBytes("Name"),"ISO8859_7");
String surname = new String(rs.getBytes("SurName"),"ISO8859_7");
System.out.println("Name:" + name + " Surname:" + surname);
</code></pre>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-18925312810505045272012-04-01T13:03:00.000+03:002013-03-29T13:06:37.548+02:00Fast file searching in C#This code shows how can you search for a file in C# using windows index and OleDB. The code below is tested
in windows Vista where file indexing is enable by default. The following function, when called,
outpust the fullpath of the file in request. It uses the operating system's file index therefore
is very fast!
<br />
<br />
<div class="source_code">
<code>
</code>
<br />
<pre><code>using System;
using System.Data.OleDb;
namespace MyBrowser
{
class Browser
{
public void findFile(string fileName)
{
try
{
string url = "provider=Search.CollatorDSO.1;" +
"EXTENDED PROPERTIES=\"Application=Windows\"";
OleDbConnection connection = new OleDbConnection(url);
string queryString = "Select System.ItemPathDisplay from "+
"SystemIndex where System.FileName ='" + fileName + "' ";
Console.WriteLine(queryString);
OleDbCommand command = new OleDbCommand(queryString, connection);
connection.Open();
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader[0].ToString());
}
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}</code></pre>
<code>
</code>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-55932191608265704682012-03-01T12:50:00.000+02:002013-03-29T13:06:24.247+02:00C++ map random valueThis code shows how can you get a random value out of a C++ map structure
<br />
<br />
<div class="source_code">
<code>
</code>
<br />
<pre><code>map<string, int> myMap;
/*
* Put code here that fills the map
*/
map<string, int>::iterator iter = myMap.begin();
map<string, int>::size_type myMapSize;
myMapSize = myMap.size();
int random_integer = intrand(myMapSize);
advance(iter,random_integer);
cout <<iter->first;
</code></pre>
<code>
</code>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-7460174240201814862012-02-01T12:37:00.000+02:002013-03-29T13:06:02.664+02:00Create a low layer network protocol with javaCreating a protocol running at layer 3, may be a hard task. But there are
times where it needs to be done quick and easy, i.e for testing protocol before
implementing it directly to the operating system's kernel. Jpcap is a
open-source, multi platform Java libray that allows protocol designers to implement
their protocol amazingly fast.<br />
<br />
Before start using Jpcap, WinPcap and Java SDK must be installed. Jpcap wan be downloaded from <a href="http://jpcap.sourceforge.net/">here</a>. The protocol that is going to be implemented is very simple.
It runs over Ethernet and it uses as addresses real names. The protocol is named
MyProtocol. The following topology is going to be used:
<br />
<br />
<pre> PC1: PC2:
mac address:00:03:0d:2e:79:68 -|switch|-mac address:00:90:96:1d:62:f8
MyProtocol address:Alice MyProtocol address:Bob
</pre>
<br />
A MyProtocol packet consists of a header and a body. The
header has an 1 byte field for the local address length, an 1 byte field for the
remote address legth, the local address and the remote address. The body just
contains some data. In this example PC1 (Alice) will send "HELLO" to PC2 (Bob).
The code for the client is quite straightforward. Initially a
the network interface to be used is located, then the ethernet packet that will
carry the MyProtocol packet is constructed and finally the MyProtocol packed is
constructed. The code for the client follows
<br />
<br />
<div class="source_code">
<code>
</code>
<br />
<pre><code>import java.util.Arrays;
import jpcap.*;
import jpcap.packet.*;
public class MyProtocol {
public static void main (String args[]){
//The local mac address
final byte[] localMacAddress ={0x00,0x03,0x0d,0x2e,0x79,0x68};
//The remote mac address
final byte[] remoteMacAddress={0x00,(byte)0x90,(byte)0x96,0x1d,0x62,(byte)0xf8};
//The index in the network interfaces list that holds the local device
int localDeviceIndex =-1;
//Obtain the list of network interfaces
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//Find the local device to use
for (int i = 0; i < devices.length; i++){
if (Arrays.equals(devices[i].mac_address,localMacAddress))
localDeviceIndex = i;
}
//Check wheather an interface with mac address same as the local mac
//address has been found
if (localDeviceIndex ==-1){ //it has not been found, break execution
System.out.println("A network interface with address equal " +
"to localMacAddress has not been found");
System.exit(-1);
}
//Create the data link packet
EthernetPacket ether=new EthernetPacket();
//Set the source address
ether.src_mac = localMacAddress;
//Set the destination address
ether.dst_mac = remoteMacAddress;
//Set the type code to a not common used value
ether.frametype = 0x0890;
//Create our protocol packet
/* Create a header. The header is of the form
*
* local address legth|remote address legth|local address|remote address
* 1 byte | 1 byte | n bytes | n bytes
*
* Suppose that the local address is Alice and the remote is Bob
*/
final byte[] myProtLcAddr = "Alice".getBytes();
final byte[] myProtRmAddr = "Bob".getBytes();
byte[] header = new byte[myProtLcAddr.length + myProtRmAddr.length + 2];
header[0] = (byte)myProtLcAddr.length;
header[1] = (byte)myProtRmAddr.length;
System.arraycopy(myProtLcAddr, 0, header, 2, myProtLcAddr.length);
System.arraycopy(myProtRmAddr, 0, header, 2 + myProtLcAddr.length, myProtRmAddr.length);
//Create the body. The body is just a hello message
byte[] body ="HELLO".getBytes();
//Build the packet
Packet packet = new Packet();
//Add the header and the body tou the packet
byte[] data = new byte[header.length + body.length];
System.arraycopy(header, 0, data, 0, header.length);
System.arraycopy(body, 0, data, header.length, body.length);
packet.data = data;
//Add the data link layer
packet.datalink = ether;
//Send the packet
try{
JpcapCaptor captor=JpcapCaptor.openDevice(devices[localDeviceIndex],1514,false,50);
JpcapSender sender = captor.getJpcapSenderInstance();
sender.sendPacket(packet);
System.out.println("Packet send");
}catch(Exception e){
System.out.println("Exception occured " + e.toString());
}
}
}</code></pre>
<pre><code>
</code></pre>
<code>
</code>
</div>
The server part is even simpler, the network interface is located and it is
set up to listen for specific ethernet type packets. The code follows
<br />
<br />
<div class="source_code">
<code>
</code>
<br />
<pre><code>import java.util.Arrays;
import jpcap.*;
import jpcap.packet.*;
public class MyProtocolServer {
public static void main (String args[]){
//The local mac address
final byte[] localMacAddress ={0x00,(byte)0x90,(byte)0x96,0x1d,0x62,(byte)0xf8};
//The index in the network interfaces list that holds the local device
int localDeviceIndex =-1;
//Obtain the list of network interfaces
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//Find the local device to use
for (int i = 0; i < devices.length; i++){
if (Arrays.equals(devices[i].mac_address,localMacAddress))
localDeviceIndex = i;
}
//Check wheather an interface with mac address same as the local mac
//address has been found
if (localDeviceIndex ==-1){ //it has not been found, break execution
System.out.println("A network interface with address equal " +
"to localMacAddress has not been found");
System.exit(-1);
}
//Open the device and loop until a packet of type 0x0890 arrives
try{
JpcapCaptor captor=JpcapCaptor.openDevice(devices[localDeviceIndex],1514,false,50);
captor.setFilter("ether proto 0x0890", true);
boolean continueCapture = true;
while (continueCapture){
Packet packet = captor.getPacket();
if (packet !=null ){ // a packet has been captured
//retreive the sender address. The firt byte stores the length
//and the address starts from the 3rd byte
String remoteAddress = new String(packet.data,2,packet.data[0]);
System.out.println("Hello received from " + remoteAddress);
continueCapture = false;
}
}
}catch(Exception e){
System.out.println("Exception occured " + e.toString());
}
}
}</code></pre>
<code>
</code>
</div>
Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.comtag:blogger.com,1999:blog-6205746452183964094.post-20956079804911269872012-01-04T13:15:00.000+02:002013-03-29T13:05:45.189+02:00Adding an applet to an XHTML pageThe traditional way to add a java applet to a web page used to be the <applet> tag but this method has been deprecated.Instead the <object> is now used.<br />
<br />
The xhtml code to add an applet is quite tricky now. Here is an example of it:
<br />
<div class="source_code">
<pre><code>
<!--[if !IE]>-->
<object classid="java:vr.class"
type="application/x-java-applet"
archive="YOUR_JAR.jar" height="HEIGHT" width="WIDTH" >
<!--[endif]-->
<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
height="HEIGHT" width="WIDTH">
<param name="code" value="YOUR_CLASS" />
<param name="archive" value="YOUR_JAR.jar" />
</object>
</code>
</pre>
</div>
More examples and a full explanation of what clsid is can be found <a href="http://ww2.cs.fsu.edu/~steele/XHTML/appletObject.html">here</a>Νίκος Φωτίουhttp://www.blogger.com/profile/03555407033025455433noreply@blogger.com