Saturday, 14 November 2009

Workaround for an issue with dojo.io.iframe.send

I've developed a widget to retrieve and update a rating in an application that resides on another domain. Due to this cross domain requirement, I had to exploit the iframe hack, which dojo toolkit implements in the dojo.io.iframe module.
It works perfectly with Firefox but I was experiencing a problem with IE 7 and Safari 4: the update went well only the first time the widged is used, afterwards no other requests were sent to the target application.

At the end I've understood that I need to create the communication iframe for every request, this is my workaround:

if ((dojo.isIE || dojo.isSafari) && dojo.io.iframe["_frame"])
{
  dojo.destroy(dojo.io.iframe['_frame']);
  var frameName = dojo.io.iframe._iframeName;
  dojo.io.iframe["_frame"] = window[frameName] = null;
  if (window.frames)
    window.frames[frameName] = null;
}
dojo.io.iframe.send(...)

Check my post to dojo-interest group for any update about this topic.

Technorati Tags:

Posted by Nicola Piccinini at 5:52 PM CET in devel/

Wednesday, 3 June 2009

Html view plugin for dijit.Editor

I've searched a bit for a plugin for dijit.Editor able to provide the HTML view of the content but I haven't found anything so I've thought it was a good occasion to try to build a plugin by myself.

Here the code, probably you want to change the module name if you try it:

dojo.provide("pc.widget.editor_html_view");

dojo.require("dijit._editor._Plugin");
dojo.require("dijit.Dialog");

dojo.requireLocalization('pc.widget', 'editor');

dojo.declare("pc.widget.editor_html_view", 
  dijit._editor._Plugin,
  {
    // Override _Plugin.useDefaultCommand... processing is handled by this plugin, not by dijit.Editor.
    useDefaultCommand: false,

    _initButton: function() {
      // Override _Plugin._initButton() to setup listener on button click

      this.command = "htmlView";
	this.editor.commands[this.command] = "HTML";
	this.inherited("_initButton", arguments);
	delete this.command;

        this.connect(this.button, "onClick", this._htmlView);
    },


    _htmlView: function() {
      this._initDialog();
      this.textarea.value = this.editor.getValue();
      this.dialog.show();
    },

    _initDialog: function () {
      if (!this.dialog) {
        this.dialog = new dijit.Dialog({}, dojo.doc.createElement('div'));
        var messages = dojo.i18n.getLocalization('pc.widget', 'editor', this.lang);
        //var buttonsHtml = '<button>Set</button><button>Set and continue</button>';
        var buttonsHtml = dojo.string.substitute('<button>${0}</button><button>${1}</button>', [
          messages['Set'], messages['Set_and_continue']
        ]);
        this.dialog.attr('content', '<div class="html-view"><div><textarea></textarea></div><div class="buttons">' + buttonsHtml + '</div></div>');
        dojo.body().appendChild(this.dialog.domNode);
        this.dialog.startup();

        this.textarea = dojo.query("textarea", this.dialog.domNode).pop();
        var buttons = dojo.query("button", this.dialog.domNode);
        this.setBtn = buttons.pop();
        this.setAndHideBtn = buttons.pop();
        this.connect(this.setAndHideBtn, 'onclick', this._replaceValueAndHide);
        this.connect(this.setBtn, 'onclick', this._replaceValue);
      }
    },

    _replaceValue: function () {
      this.editor.replaceValue(this.textarea.value);
    },
    _replaceValueAndHide: function () {
      this._replaceValue();
      this.dialog.hide();
    }
  }
);

// Register this plugin.
dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o) {
  if(o.plugin){ return; }
    switch(o.args.name) {
      case "htmlView":
	o.plugin = new pc.widget.editor_html_view({command: o.args.name});
    }
});

Here you can see it in action:
http://superfluo.org/blojsom-resources/htmlView-dijit.Editor/editor
and here you can list and download all files:
http://superfluo.org/blojsom-resources/htmlView-dijit.Editor/

Posted by Nicola Piccinini at 5:47 PM CEST in devel/

Sunday, 14 December 2008

Geokit geocoding with multiple matches

Do you want to be able to manage multiple geocoding matches with Geokit?

>> g = Geokit::Geocoders::GoogleGeocoder.geocode('Springfield')
=> #<Geokit::GeoLocs:0x7f0705acb288 ...
>> g.full_address
=> "Springfield, MO, USA"
>> g.ll
=> "37.196828,-93.287061"
>> g.size
=> 9
>> g.map {|e| e.full_address}
=> ["Springfield, MO, USA", "Springfield, Florida, USA", "Springfield, IL, USA", "Springfield, Missouri, USA", "Springfield, MA, USA", "Springfield, Virginia, USA", "Springfield, OH, USA", "Springfield Ave, Paris, IL 61944, USA", "Springfield, Baldwin, MI 49304, USA"]
>> g.is_a? Geokit::GeoLoc
=> true

Give a try to my simple enhancement (only for Google geocoder) and let me know.

Technorati Tags:

Posted by Nicola Piccinini at 4:40 PM CET in /

Friday, 5 December 2008

Posting a file with ActiveResource

Recently I had to put or post files to a web service using ActiveResource. I thought that it was a common tasks but, after searching a bit, I wasn't able to find any documentation about how to do that and so I ended up implementing my dirty solution.

Luckily, Rails already knows how to parse a file parameter so I only had to produce an XML conforming to what that parameter parser expects. If you, like me, are receiving the file from a multipart/form-data form in a Rails application, then you have an UploadedStringIO instance to play with:

module ActionController
  class UploadedStringIO
    def to_xml(options = {})
      options[:indent] ||= 2
      xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
      xml.instruct! unless options[:skip_instruct]
      dasherize = !options.has_key?(:dasherize) || options[:dasherize]
      _root = options[:root] || 'file'
      root_tag = dasherize ? _root.to_s.dasherize : _root.to_s
      xml.tag!(root_tag, ActiveSupport::Base64.encode64(string), :type => 'file', :name => original_path, 
        (dasherize ? 'content-type' : 'content_type') => content_type)
    end
  end
end

With that, if you have a Tournament model, with a flier attribute and you assign to it a text file (file name: flier.txt, file content: abc) then ActiveResource will post/put something like:

<?xml version="1.0" encoding="UTF-8"?>
<tournament>
  <flier type="file" name="flier.txt" content-type="text/plain">YWJj
</flier>
</tournament>

that is what Rails wants.

Technorati Tags:

Posted by Nicola Piccinini at 6:03 PM CET in devel/

Sunday, 30 November 2008

Relay mail via Google SMTP or AuthSMTP with Postfix

A well know trouble with EC2 instances is to send mail reliably, in fact the dynamic nature of the IP numbers in the cloud makes them suspect for most spam countermeasures. The common workaround is to have an external SMTP server thorough which relaying every email message.

A natural choice is to use Google Apps for your domain and to exploit their service which is free up to 2000 messages per day and comes with all the Gmail goodies.
Jules Szemere has a good post (1) about how to do that with Postfix (note for Ubuntu users: the CA.sh script is in /usr/lib/ssl/misc).

Unfortunately, in my experience (and not only in mine) also messages from Google servers are sometimes considered SPAM. Perhaps switching to the premium edition could solve that, anyway I followed the recommendation (2) from Paul Dowman (EC2 on Rails author) and I'm using AuthSMTP. The minimum fee is lesser than Google Apps premium edition (though the cost per message is not) and it's actually reliable.

What I miss more with AuthSMTP is the lack of a copy of the message in the sent mail folder, I could always add a BCC field but this wastes the service quota.
The ideal solution is to use Google to send to safe addresses that are unlikely to drop the message (especially those in BCC) and to use AuthSMTP otherwise. In practice we have to put together the configurations in (1) and (2) in a smart way. So, thanks to the suggestions of my trusty system administrator, in /etc/postfix/main.cf:

transport_maps = hash:/etc/postfix/transport

# auth
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd

# tls
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
smtp_tls_note_starttls_offer = yes
tls_random_source = dev:/dev/urandom
smtp_tls_scert_verifydepth = 5
smtp_tls_key_file=/etc/postfix/certs/postfixclient.key
smtp_tls_cert_file=/etc/postfix/certs/postfixclient.pem
smtpd_tls_ask_ccert = yes
smtpd_tls_req_ccert = no
smtp_tls_enforce_peername = no

Two maps need to be specified, transport_maps defines which relay server to use depending on the destination address:

gmail.com   :[smtp.gmail.com]:587
yahoo.com   :[smtp.gmail.com]:587
*           :[mail.authsmtp.com]

while smtp_tls_policy_maps defines the policy to use with the relaying server:

[mail.authsmtp.com]             none
[smtp.gmail.com]:587            may

Finally, in smtp_sasl_password_maps we specify both Google and AuthSMTP credentials:

gmail-smtp.l.google.com username@yourdomain.com:password
smtp.gmail.com username@yourdomain.com:password
mail.authsmtp.com username:password
Posted by Nicola Piccinini at 5:19 PM CET in devel/

Tuesday, 1 April 2008

Английски

All my solidarity to Valentina Hasan, I never understand lyrics!

(via)

Posted by Nicola Piccinini at 10:56 PM CEST in /in the net/

Wednesday, 12 March 2008

mongrel_rails service and $stdout problem on Windows server

Charlie:

First, if you have the choice, ditch windows, not worth it. However, if you are like me and are forced to use windows for a project then your solution is a simple derivative of what you will find here.

I'm forced to work with a Windows server too and I was experimenting the same issue. Charlie put me on the right track and I solved it adding what follows at the beginning of #{RAILS_ROOT}/config/boot.rb:

begin
  $stdout.write("checking $stdout -> ")
  $stdout.flush # really try to write!
  $stdout.write("OK\n")
rescue
  $stdout.reopen('log/mongrel.log')
  $stderr.reopen('log/mongrel_err.log')
end

As $stdout and $stderr are redirected only when IO#write raises an exception, it is effective only when Mongrel is running as a service and you still can launch it from a terminal or use a console without any problem.

Posted by Nicola Piccinini at 12:57 AM CET in devel/

Tuesday, 13 November 2007

Experimenting with MySQL spatial extensions

Two years ago I was experimenting with PostGIS on etch and in these days I'm trying to do the same with MySQL. I'm no longer maintaining a page with my system configuration because It was more annoying than useful (at least for me ;-P ), it should be enough to know that we are on a debian lenny, with MySQL 5.0.45-1.

To test the spatial extensions of MySQL, I'll use again the free GIS data about world borders. The first step is to convert the shape file in a SQL script suitable for MySQL:

  • download shp2mysql from http://kartoweb.itc.nl/RIMapper/ (currently it's at version 0.4);
  • compile it. Assuming that all needed library and header files are installed in the system, it's sufficient to do:
    $ gcc -lshp shp2mysql.c -o shp2mysql
    
  • the usage is analogous to shp2pgsql, for example:
    $ ./shp2mysql -s 4326 ../../geo_data/world_borders/world_borders.shp world_borders db_name > world_borders.mysql.sql
    

Now you you can execute the obtained SQL script in a MySQL database and then query the world_borders table:

> select CNTRY_NAME from world_borders where Contains(ogc_geom, GeomFromText('Point(13 40)')) = 1 ;
+------------+
| CNTRY_NAME |
+------------+
| Italy      | 
+------------+
1 row in set (0.41 sec)

and that's fine.

Without the need of loading GIS data we can try some geometric functions:

> select Glength(GeomFromText('LINESTRING(12 34, 13 35)')) ;
+---------------------------------------------------+
| Glength(GeomFromText('LINESTRING(12 34, 13 35)')) |
+---------------------------------------------------+
|                                   1.4142135623731 | 
+---------------------------------------------------+
1 row in set (0.00 sec)

From MySQL 5.0 reference manual:

In MySQL, the SRID value is just an integer associated with the geometry value. All calculations are done assuming Euclidean (planar) geometry.

Does it mean that you can't do geometric calculation on spheroid with MySQL spatial extensions? I don't think so, maybe it's only a bit more complicated, read this enlighten (for me) thread: MySQL GIS

A final note: both PostgreSQL with PostGIS and MySQL spatial extensions work well under Microsoft Windows. I know it because not every coworker uses GNU/Linux, unfortunately ;-) .

Pingbacks:
2008-Jun-18 CEST: &raquo; .SHP to MySQL
Posted by Nicola Piccinini at 12:18 PM CET in geo/

Wednesday, 31 October 2007

Omar

Today:
Omar

For equal opportunities ;-), about 3 years ago, when I haven't a blog:
Enrico

Pingbacks:
2007-Nov-01 CET: Fermati al mulino

Technorati Tags:

Posted by Nicola Piccinini at 11:53 PM CET in /

Wednesday, 22 August 2007

dojo 0.4.x to 0.9 porting

I've just ported a bunch of code from dojo 0.4.x to 0.9 and I like to share some brief considerations, in the hope that they could be useful for somebody:

  • most of the job consists of searching and replacing some common patterns, for example: widget declaration and creation, second argument in topic publishing method (that now is an array), etc. (see the porting guide). It's boring but easy;
  • exotic usage of the dom node used in widget creation can cause problems because it seems that dojo 0.9 substitutes it with a new source dom node. In such cases a slightly refactoring is usually needed;
  • what I initially missed more was the unavailability of debugAtAllCosts and dojo.hostenv.writeIncludes() but luckily the same problem (debugging evaled code) is solved in a better way by Fireclipse;
  • some features are missing in dojo 0.9 but usually there is another way to achieve the same effect or one can solve the problem copying and adapting the right functions from 0.4.x.

After (to be honest) a lot of work I've completely refactored my application that consists approximatively in 15 widgets and 25 other Javascript source file (divided into two modules).

Unfortunately I can't yet precisely evaluate any performance gain because I'm having problem with the build system and the flattening of localization bundles and I'm not able to build a working release (I believe it's a bug of the build system but can't prove that ;-). Anyway:

  • the (gzipped) size of the release is about 25% less than with dojo 0.4,
  • rendering seems a lot faster in 0.9 respect to 0.4 (no numbers, just feelings).

In conclusion, it seems that the porting to dojo 0.9 has improved my application performance but the gain isn't so impressive. In my opinion it's better to promptly follow the evolution of the library, so I believe that it's worth to upgrade anyway.

Technorati Tags:

Posted by Nicola Piccinini at 1:02 AM CEST in devel/
« February »
SunMonTueWedThuFriSat
 123456
78910111213
14151617181920
21222324252627
28