ラベル C# の投稿を表示しています。 すべての投稿を表示
ラベル C# の投稿を表示しています。 すべての投稿を表示

2007/03/17

BloggerのFeedにも「続きを読む」を適用してみる。

無精をしたいが為に何通りかの方法を試してみたりしてきたBloggerでの「続きを読む」機能ですが、現在はtemplate + javascriptな方法で運用中です。

このFeedを読んでいる方には迷惑な話かもしれませんが、もう少し「続きを楽しむ」って事で、Feedにも適用してみました。


RSSなりAtomなFeedをBlog Readerで購読していると、見かけるのが記事全文を表示しないタイプのFeedです。

BloggerでもSummaryなFeedが用意されているのですが、これは先頭からの文字数規定でSummaryとするタイプであり、折角「続きを読む」な書き方をしているのにちょっと理不尽な感じがしまして、別サーバーを介して<div class="fullpost">内を削るFeedを作ってみました。

実際には私はFeedburnerを利用していますので、こちらにもSummary機能はあるのですが、こちらも規定文字数までを出力するタイプなので、FeedburnerのFeed元を自サーバーに変更して対応しました。

サーバーはASP.Netな環境であり、今回のFeedはc#で書かれたaspxページで提供されています。

BloggerのコンテンツはXHTML 1.0 Strictだと思っていたのですが、私個人がそれをやや無視したコンテンツを書いていたり、Picasaから投稿した際に生成されたと思われる画像への<a>タグのAttributeの記述で要素間の空白が無いケース等があり、xmlなパーサー使って読み込んでremoveChildで消せば楽々だとかの思いは適いませんでした。

今更過去に書いたPostの細部を確認しながら修正する気力も湧かないなかったので、XML Parserを使うのではなく正規表現を交えたコードでゴリゴリと<div class="fullpost">を消しこむようにしました。

それほどASP.NetなサーバーをBloggerのFeedの加工なんかに利用できる方もいるとは思えませんが、コードはこんな感じです。

public partial class atom : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        XmlDocument xml = new XmlDocument();
        WebClient webClient = new WebClient();
        String sFeed = (Request["feed"]!=null
                    ?Request["feed"]
                    :@"http://isawseashell.blogspot.com/feeds/posts/default" );
             
        Stream webDataStream = webClient.OpenRead(sFeed);

        xml.Load(webDataStream);

        XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
        nsmgr.AddNamespace("atom""http://www.w3.org/2005/Atom");


        XmlNodeList contents = xml.SelectNodes("//atom:entry//atom:content", nsmgr);

        foreach (XmlNode content in contents)
        {
            string sContent = content.InnerText;

            sContent = removeFullpost(sContent);

            content.InnerText = sContent
                + "<br/>【記事全文はBlogサイト I saw seasheels. にて!!】";

        } // __forEach

        Response.Write(xml.OuterXml);

    }

    //
    private string removeFullpost(string sContent)
    {

        Regex rexp = new Regex("<div.*class=.*fullpost.*>");

        int nStartPos = rexp.Match(sContent).Index;

        if (nStartPos > 0)
        {
            int nEndPos = findEndTag(sContent, nStartPos, "div");

            sContent = sContent.Substring(0, nStartPos)
                    + (nEndPos + "</div>".Length + 2 <= sContent.Length
                        ? sContent.Substring(nEndPos + "</div>".Length + 2)
                        : "");
        }

        return sContent;
    }

    private int findEndTag(string s, int nStartPos, string sTagName)
    {
        Regex rexpEnd = new Regex("</" + sTagName + ".*>");
        Regex rexpStart = new Regex("<" + sTagName + ".*>");

        int nEndPos = rexpEnd.Match(s, nStartPos + 1).Index;
        int nInnerStart = rexpStart.Match(s, nStartPos + 1).Index;
        if (nInnerStart > 0 && nInnerStart < nEndPos)
        {
            nStartPos = findEndTag(s, nInnerStart, sTagName);

            nEndPos = findEndTag(s, nStartPos, sTagName);
        }
        else
        {
            nEndPos = rexpEnd.Match(s, nStartPos + 1).Index;
        }

        return nEndPos;
    }

}


省略時の文言もパラメータにしようとかは思っていますが、現在はこんな感じて書いてあります。そしてこれをホスティングしているサーバーのURLをFeedBurnerのFeed元に指定しいます。

今現在このBlogのFeedを見ると記事が省略されいるかと思います。

このコードをHostingしているサーバーの規約・制約があるのでサービスとして公開する事は出来ませんが、Adsense等の広告収入がServerのレンタル代(月1000円程度)をカバー出来るようになったらなぁ・・とかと夢を見ています(笑

こんな感じで実はちょっと迷惑は機能を実装したりして、自己満足に浸っていられるのがPrivateなBlogの良さではないかと。

続きを読む・・

2007/01/28

VS.PHP (2)

VS.PHP 使ってみてますが、なんかシックリきません。なんというか取り合えず使えるようにしましたってレベルから抜け出てない感じがしてます。

コード書いていて、Intellisenseはincludeしたオブジェクトに対しても使えたりできるので便利ではありますが、評価できるのはこの辺りぐらいかと。なんかインデントの処理とかも変な感じで、突然手前のタブに落とされたりするのが不快であったり。

PHPなんでコンパイルやBuildって概念は基本的にないんでしょうけど、C#なVB.NETなASP.NETがBuildにより実行前にコードの評価がしてもらえるのに比べて、実行時に初めてエラーとなる=ブラウザ上にエラーが表示ってのがもどかしい。

Debug面では変数のWatchに関しては、日本語が入るとArray系の展開はダメダメです。またImmediate Windowは使えない(機能しない)です。変数Watchに関してはAuto・Localも所詮はPHPなんでみたないな・・・。

それとコードのReleaseというかPublish、つまりはFTP等によるServer上へのコピー機能ぐらい付けてよと。

VS.PHPというよりもPHPやDBGなりの機能・仕様による制限的な面も大きいのでしょうが、あまり期待してはいけないのかなぁと。

続きを読む・・

2007/01/23

via Proxy.

今日はフランスはパリ13区にお住まいの、Rachel Roblin(仮名)さんからの質問にお答えしたいと思います。

CSharpでWebBrowserControlを使った簡易なインターネットブラウザを作ってるんだけど、Proxyサーバーの設定方法がわからないんだ。

もちろん、Internet Explorerの設定を共有しているのは知ってるよ。だけど、FireFoxとIEの関係みたないに独立した設定がしたいんだ。

僕の作ったBrowserの為にIEの設定まで変更されてしまうのはどうかなと思うし。

不思議な事にControlのプロパティにもメゾッドにもそれらしき項目は無いんだよ。

何か方法はない?

こんなFrenchな人のFrankな質問メールですが、ちょっと調べてみましたが確かに該当するPropertyもMethodも無いんですね。

IEのコンポーネントになんて長いこと使ってなかったのですが、Urlmon.dllで確かって記憶が残ってました。実際に調べてみるとUrlMkSetSessionOptionとかで自プロセスで扱うコンポーネントのProxy設定とかが出来るようです。

C#はそれなりに便利にAPIを呼ぶ仕掛けが用意されているのですが、構造体とか入ってくるとちょっと難易度は上がります。というかかなり変態なコードになるので、通常のBusiness Logicなんか書いてあるファイルには書きたくない感じになります。

とりあえず、こんなコードを書いてみました。



using System;
using System.Runtime.InteropServices;

class urlmon
{
[DllImport("urlmon.dll", CharSet = CharSet.Ansi)]
private static extern int UrlMkSetSessionOption(
int dwOption, IntPtr pIpi, int nLength, int dwReserved);

public enum InternetOpenType: int{
INTERNET_OPEN_TYPE_PRECONFIG = 0 // use registry configuration
,INTERNET_OPEN_TYPE_DIRECT = 1 // direct to net
,INTERNET_OPEN_TYPE_PROXY = 3 // via named proxy
,INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 4 // prevent using java/script/INS
}

private struct INTERNET_PROXY_INFO
{
public InternetOpenType dwAccessType;
public IntPtr proxy;
public IntPtr proxyBypass;
};

//
public static int InternetOptionProxy(InternetOpenType nOpenType)
{
return InternetOptionProxy(nOpenType,"","");
}

//
public static int InternetOptionProxy(InternetOpenType nOpenType
, string proxy, string proxyBypass)
{
const int INTERNET_OPTION_PROXY = 38;

INTERNET_PROXY_INFO ipi;
ipi.dwAccessType = nOpenType;
ipi.proxy = Marshal.StringToHGlobalAnsi(proxy);
ipi.proxyBypass = Marshal.StringToHGlobalAnsi(proxyBypass);

IntPtr pStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(ipi));
Marshal.StructureToPtr(ipi, pStruct, true);

return UrlMkSetSessionOption(INTERNET_OPTION_PROXY, pStruct, Marshal.SizeOf(ipi), 0);
}
}


クラス名とかはurlmon.dllを呼び出すコードを誰かが書き足してくれればという願いを込めて付けましたりしてますし、本来はPropertyとしてGet,Setを実装すべきだろうとは思いますが、自分で使わないのと説明がメインのコードなんで。

Function自体はstaticになっているので、以下のような感じでWebBrowserControlの貼ってあるFormのLoadイベントとかで呼び出せばいいんではないでしょうか。設定変更があるならば、その都度呼んでも良いと思いますし。

urlmon.InternetOptionProxy(urlmon.InternetOpenType.INTERNET_OPEN_TYPE_PROXY, "localhost:8080", "");

というわけでRachel 、また旨いワイン奢ってね。

続きを読む・・

2006/12/26

Economical Project

最近ちょっとPrivateで知人に頼まれてDesktopなdotNetアプリケーションをASP.NET化したんですが、追加要望でコツコツと手を入れています。

Hosting場所は私がテスト用に使ってるServerだったりもしますがソースも完全に渡してるんで、もう自分で好きにしてよって感じもしますが、なにやらノせられてプロジェクト(?)は続いております。.NetにしてもC#にしても、私はPGとしての第一線からちょっと離れてしまってたので、調べながらやるのは依頼主と一緒なんですけどね。

今やってて何がダメかっていうと、二人ともデザインセンス無し(笑。 センスも無ければやる気も無しって状態に近いかと。質実剛健といえば聞こえはいいですが、お遊び用のコードなんで例外処理とか抜きまくりだし・・・。

それとテスト用に無償で借りてるHosting ServiceなんでDatabaseも容量は小さく、Transaction log領域なんて寂しい限りです。最大80,000行のレコードを挿入してからQueryで集計処理とかあったんですが、一回は出来ても次から無理ですから。Deleteすら出来はしないみたいな感じで、面倒だから集計処理後にTruncate tableとか入れたりしてました。

結局はこんな集計はデータ作成時にコード上でやれば、テーブルにレコードを挿入する必要ないでしょって事で、コードを大幅書き直し。パフォーマンスも大幅Upでクライアントも大満足みたいな結果は出ましたが。

たまにはこんな激貧Projcetもまた楽しいかと。

続きを読む・・

2006/10/13

SSLStream for GMail POP3s

GMailに大変お世話になっています。

未だにβ版とはいえ便利すぎて手放せません。まぁGMailFSとかも使ってるからですが。
POP3に対応というかPOP3s 対応しているのもちょっと魅力。

それで以前にC#でTLS物を作ろうとして苦労をしていたのを思い出したのですが、.NET 2.0なるとSSLStreamとかってクラスが追加されてて、簡単に出来そうな感じだったので試してみました。



元のサンプルプログラムを弄っただけもので、あくまでもクラスのテスト用のコードですが。


using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
namespace ConsoleSecureTcpClient
{

    class SecureClient
    {

        [STAThread]
        static void Main()
        {
            string server = "pop.gmail.com";
            string sUser = "USER " +  "Your Account@gmail.com" + "\r\n";
            string sPassword = "PASS " + "Your Password" + "\r\n";
            int port = 995;
            SslStream stream = null;

            try
            {
                // Instantiate a TcpClient with the target server and port number
                TcpClient client = new TcpClient(server, port);

                // Specify the callback function that will act as the validation delegate. This
                // lets you inspect the certificate to see if it meets your
                // validation requirements.
                RemoteCertificateValidationCallback callback =
                                                    new RemoteCertificateValidationCallback(OnCertificateValidation);

                // Instantiate an SslStream with the NetworkStream returned from the TcpClient.
                stream = new SslStream(client.GetStream(), false, callback);

             
                // As a client, you can authenticate the server and validate the results using the SslStream.
                // This is the host name of the server you are connecting to, which may or may not
                // be the name used to connect to the server when TcpClient is instantiated.
                stream.AuthenticateAsClient(server);
                if (stream.IsAuthenticated)
                {
                    // Indicates whether the authentication was successful.
                    Console.WriteLine("IsAuthenticated: {0}", stream.IsAuthenticated);
                    // Indicates whether both the client and server has been authenticated.
                    // In this example only the server is authenticated.
                    Console.WriteLine("IsMutuallyAuthenticated: {0}", stream.IsMutuallyAuthenticated);
                    // Indicates whether the SslStream uses data encryption.
                    Console.WriteLine("IsEncrypted: {0}", stream.IsEncrypted);
                    // Indicates whether the data sent is signed.
                    Console.WriteLine("IsSigned: {0}", stream.IsSigned);
                    // Indicates whether the current side of the connection is authenticated as a server.
                    Console.WriteLine("IsServer: {0}", stream.IsServer);
                }

                Byte []data = new Byte[256];
                int bytes = stream.Read(data, 0, data.Length);
                string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);

                data = System.Text.Encoding.ASCII.GetBytes(sUser);
                stream.Write(data, 0, data.Length);
                Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));

                data = new Byte[256];
                bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);

                data = System.Text.Encoding.ASCII.GetBytes(sPassword);
                stream.Write(data, 0, data.Length);
                Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));
             
                data = new Byte[256];
                bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);

                data = System.Text.Encoding.ASCII.GetBytes("QUIT\r\n");
                stream.Write(data, 0, data.Length);
                Console.WriteLine("Sent: {0}", Encoding.ASCII.GetString(data));
             
                data = new Byte[1024*1024];
                bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);

            }
            catch (AuthenticationException ex)
            {
                Console.WriteLine(ex.Message);
            }
            catch (SocketException ex)
            {
                Console.WriteLine(ex.Message);
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                // Make sure that the SslStream is closed.
                if (stream != null)
                    stream.Close();
            }

            Console.WriteLine("\n Press Enter to continue...");
            Console.Read();
        }
        // Check the certificate for errors and to make sure it meets your security policy.
        private static bool OnCertificateValidation(object sender, X509Certificate certificate
                    , X509Chain chain, SslPolicyErrors errors)
        {
            Console.WriteLine("Server Certificate Issued To: {0}", certificate.GetName());
            Console.WriteLine("Server Certificate Issued By: {0}", certificate.GetIssuerName());
            // Return true if there are no policy errors
            // The certificate can also be manually verified to make sure it meets your specific
            // policies by interrogating the x509Certificate object.

            if (errors != SslPolicyErrors.None)
            {
                Console.WriteLine("Server Certificate Validation Error");
                Console.WriteLine(errors.ToString());
                return false;
            }
            else
            {
                Console.WriteLine("No Certificate Validation Errors");
                return true;
            }
        }
    }
}


以前は、Mentalis.org Security Library を使用して満足していましたが、Frameworkに入ったという事でこれはこれでよい感じです。

しかしFrameworkもここまでくると、IntelliSense無しのCodingはちょっと辛いですね。

続きを読む・・