Preparing HTML for print

2011/05/09

The challenge

Getting a HTML out of a printer for book-production, for example, is quite a challenge: Getting the page-breaks right, getting the CSS right and so on and so on.

CSS standards

Luckily, CSS 2.1 supports Print-media-specific standards for this (for example: http://www.westciv.com/style_master/academy/css_tutorial/advanced/printing.html),  Sadly, this is not completely, or improperly supported, by most HTML clients we have at this moment. (see http://www.webdevout.net/browser-support-css#css2propsprint for a nice overview of support per browser, sadly not updated for Firefox version 4 yet, which DOES support some of it)

First: An example of what to include in your CSS for printing:

<style type="text/css">
@media print {
 .alwaysbreak {
   page-break-before: always;
 }
 .nobreak {
   page-break-inside: avoid;
 }
 @page :left {
   margin: 1cm;
   margin-right: 2cm;
 }

 @page :right {
   margin: 1cm;
   margin-left: 2cm;
 }
}
</style>

As you can see, above I tried to make each left page of the book have a wider right-margin, each right page of the book have a wider left-margin. Ideal for double-sided prints for books.

I also declared a class ‘nobreak’ that will make sure any contents of any <table> or <div> element using it, will no be broken up for a page break, but instead moved to the next page. Then there is the ‘alwaysbreak’ that does almost the opposite: It makes sure the inner contentst are always started at a new page. Both could be used like this:

<div class='alwaysbreak'>
  <h1>Always at a new page</h1>
</div>
<div class='nobreak'>
  <img src='mypicture.jpg' />
  <p>Caption, should never be broken from the image by a page-break</p>
</div>

Client support

You can imagine other classes too, like ‘neverbreakafter’ that will try to make sure your contents are not broken up in an ugly manner.

While preparing my children’s ‘first years’ book, I tried several clients to render my HTML to a proper PDF (also see this outdated article http://stackoverflow.com/questions/117772/which-browsers-support-page-break-manipulation-using-css-and-the-page-break-insid):

  • Internet Explorer: Only respects ‘page-break-after’ and ‘page-break-before’. And not in a very reliable way.
  • Chrome: Older versions accepted some of the standard, newer versions have broken it. iow: Not reliable
  • Firefox: Since version 4, which was JUST released, it finally supports all page-break-* tags in a nice way, but not the ‘widows/orphans’ and page-left / page-right margins, and rendering is flaky, to say the least.
  • Prince 2: http://www.princexml.com/ It promised to be the best, *does* support everything, but, with the latest beta 8, just renders my images-filled tables, the most important part of my books, completely wrong. Even worse: It renders the last column in the outer margins and even bleeding outside the page! Also, Prince is VERY ‘restrictive’ on the accepted incoming HTML, as it should be completely XHTML compliant. In practice, almost no webpage is *completely* xhtml compliant. For example: http://www.google.nl is not even accepted and it keeps complaining about ‘&nbsp;’ entities not being accepted. Ofcourse, this last error is fixable, but c’mon!!!! Just not practical and too much a ‘let the user sort it out’ approach. And then they ask money to NOT have a logo on your first page. 😦 On a sidenote, JavaScript support is ‘beta’, not supporting ‘innerHTML’, so jQuery
  • Opera: Tested with version 11, the latest, it supports everything!!!!!!!!!!!!!!!!!! One big problem with Opera: When rendering images to a printer, it uses the resolution of the screen-version of the images. Say you have an image of 1000×1000 pixels, and you include it as an IMG element with width=’250px’ height=’250px’, then it will just render it to the printer too as 250x250px. Whereas IE, Chrome, Firefox would just render it as a higher-density image! So, Opera is a no-go too. (And no, Print To File did not solve this either)
  • WKHTML2PDF: http://code.google.com/p/wkhtmltopdf/ IT DOES EVERYTHING! WOW! After one day of tweaking my HTML for almost every browser out there, THIS command-line tool just does it all. Be sure to get the ‘statically linked’ version, on my Windows test system if worked flawlessly. Supports higher density images for print, page-break-inside, page-break-after etc., correct header and footer, title page, generation of TOC. Wow!

AllSolutions’ WebSolutions: Uren loggen op Linux

2011/05/09

Want het werkt ‘alleen met IE6’, wat wel een BEETJE waar is.

Dus hoe toch te doen:
1. User Agent Switcher installeren in FireFox:
2. Naar deze pagina gaan:
  • https://ws.ict.nl/
  • Nu in adresbalk dit plakken:
    javascript:s=parent.login.appl.location.href;s=s.replace(‘start’,’launchmurreg’);window.open(s,’_newtab’);void(0);
  • En op enter drukken, de ‘urenregistratie’ opent in een nieuw tabje
3. Bookmarklet maken van javascript trucje:
  • Voeg een bookmark toe aan de “Bookmark bar” (rechtsklikken op bookmark bar -> Add Page)
  • Als URL hetzelfde JavaScript toevoegen, als naam wat jij wilt
  • Als je nu ooit weer naar https://ws.ict.nl toe gaat, dan gewoon de net aangemaakt bookmark kiezen om direct naar urenregistratie te gaan in een nieuw tabje.

Using Android SDK Manager with HTML proxy

2011/05/09

When you’re behind a NTLM proxy, or some other proxy requiring authorization, using the Android SDK Manager from Eclipse will not work to download, for example, Android packages.

Solution: Start the SDK manager from the command line (or Windows Explorer or Nautilus or whatever you use) in the tools/ directory of the downloaded Eclipse SDK you extracted on your zip. Configure the proxy settings there, accept possible errors popping up, and close the SDK Manager. Start the SDK Manager from the Eclipse environment again, and voila, the proxy CAN be configured.

All thanks and respect to my esteemed collegue who just started working for my company and already made quite a name in the hallway here, being buzzed around and chatted about by everyone, from technical staff upto and until higher management, who not only knows us this way, but also already is acquinted with famous people in our country, like Erik de Zwart, the Radio DJ, from his former employer. His name? Eric de Vries.


Ruby and Oracle Enhanced Adapter: Strange date values causing errors

2009/10/29

Seems that oracle not only allows ‘null’ dates, but also ’empty’ dates. On ’empty’ dates, the error would come up! I totally misjudged the results of the error then, it seems…

Below is what I changed in oracle_enhanced_oci_connection.rb in lib\ruby\gems\activerecord-oracle_enhanced-adapter-1.2.1\lib\connection_adapters\. The changed lines are marked with #MVR as comment above it. All I did is make ’empty’ dates detectable and skip converting them to a date too, effectively making them ‘null’ values too 😉 Starts around line 128:


# ruby-oci8 1.0 returns OraDate
when OraDate
# MVR: treat 'empty' date/time strings as null too!
if !(v.hour == 0 && v.minute == 0 && v.second == 0 && v.year == 0 && v.month == 0 && v.day == 0)
# RSI: added emulate_dates_by_column_name functionality
if OracleEnhancedAdapter.emulate_dates && (v.hour == 0 && v.minute == 0 && v.second == 0)
v.to_date
else
# code from Time.time_with_datetime_fallback
begin
Time.send(Base.default_timezone, v.year, v.month, v.day, v.hour, v.minute, v.second)
rescue
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
::DateTime.civil(v.year, v.month, v.day, v.hour, v.minute, v.second, offset)
end
end
end
# ruby-oci8 2.0 returns Time or DateTime
when Time, DateTime
# MVR: treat 'empty' date/time strings as null too!
if !(v.hour == 0 && v.minute == 0 && v.second == 0 && v.year == 0 && v.month == 0 && v.day == 0)
if OracleEnhancedAdapter.emulate_dates && (v.hour == 0 && v.min == 0 && v.sec == 0)
v.to_date
else
# recreate Time or DateTime using Base.default_timezone
begin
Time.send(Base.default_timezone, v.year, v.month, v.day, v.hour, v.min, v.sec)
rescue
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
::DateTime.civil(v.year, v.month, v.day, v.hour, v.min, v.sec, offset)
end
end
end
else v
end

Hope this is of any help to those fighting with Oracle 😉 Cheers


Ruby 1.9: Installing on Windows

2009/10/29

Below some notes I jotted down while trying to install a complete Ruby 1.9 environment for me to work with on…. *shudder* Windows *shudder.

Why the *shudder* ? Because some ‘plugins’ for Ruby (gems) require you to build it from sourcecode (make with mingw32 C++ compiler) which leads to all kinds of errors, the first one you’ll see is:  “You’ll have to install development tools first.”. So here’s what I did:

  1. Install the Ruby 1.9 one-click installer into D:\Ruby19 from http://rubyforge.org/frs/?group_id=167&release_id=38052, there select the rubyinstaller-1.9.1-p243-preview2.exe download.
  2. Add D:\Ruby19\bin to the environment PATH variable
  3. Open a command prompt and type ‘gem install scrubyt’. This leads to the above-mentioned error about no development tools found to create a make file etc. etc. etc.
  4. Find this post: http://programming-gone-awry.blogspot.com/2009/05/ruby-19-one-click-installer.html and follow it’s instructions.
  5. From the same RubyForge page as above, download the “devkit-3.4.5r3-20090411.7z” file too and unpack it into the D:\Ruby19 folder.
  6. Change paths in D:\Ruby19\devkit\msys\1.0.11\etc\fstab to point to D:\Rub19 instead of C:\Ruby
  7. Check installation of devkit with “gcc -v” in command prompt
  8. Check whether installation of binary gems work by using, for example, “gem install scrubyt”

I will post more messages regarding choosing a good IDE for Ruby on Rails development and any issues I encountered while developing my Oracle10 RoR application.


Fixing Oracle 8i ‘ORA-00904: invalid column name’ on export

2009/09/09

One of those days: You just want to migrate an ancient Oracle 8i database to a fresh ‘new’ Oracle 10g instance, when a simple bog-standard export (exp.exe) fails, displaying this dreaded error:

EXP-00008: ORACLE error 904 encountered
ORA-00904: invalid column name
EXP-00000: Export terminated unsuccessfully

---- start rant here ----

Ofcourse, no help provided as Oracle likes you to get your hands dirty (yes, pun intended): Tracing and monitoring SQL calls made by it’s exp.exe utility (and don’t even dare to use a utility for this they supplied themselves with Oracle 8), reading through log files, searching the internet to find what those SQL calls you finally found actually mean… the whole lot. Try that, if you’re not doing Oracle 24/7!

Somehow I always get somewhat ‘aggregated’ when a product is this ‘arrogant’, just assuming you live to work with it and have nothing else to be interested in! Even worse: When they supply tools with their product, that are as equally arrogant: If everything is configured OK, the tool works perfectly. But if something is wrong, you’ll tell the user nothing more than that something is wrong, leaving the user clueless and without a hint towards a solution. If there is one at all. Try letting the customer pay for that….

----- end rant here ----

Finding a solution:

Reading the error literally, I assumed one of my database’s column names were invalid, using some kind of Oracle / Java keyword that only on export would cause some kind of ‘clash’. As the error appeared while exporting Sequences, I searched through my primary key field names but found nothing wrong, from the looks of it. In the export’s parm file, I even tried exporting only specific tables, or just one table, to eliminate which table’s field names could cause the error…. Nothing.

As I knew my database was not using any of the Java magic internally, I searched the internet to find a way of ‘disabling’ support for Java in my database, trying to get the database to the most ‘basic’ state I could imagine. And then I arrived, after a long search, at this post on LazyDBA, referring to ORACLE MetaLink DocID 196921.1 (Oracle Meta…. WHAT? Geez…):

If Java is enabled, the Export utility uses DBMS_JAVA.LONGNAME in a query
while exporting synonyms. If the DBMS_JAVA or DBMS_JAVA_TEST package has not been
installed or somehow cannot be executed, this query will fail with and ORA-
00904: “invalid column name”.

Derived from the comments made in this post and the Oracle article, I came to the following steps to repair my Oracle database.

The solution:

Warning: Following these steps will complete remove the Java support for your database. In the Metalink article, and in the LazyDBA post, you’ll also find instructions on how to re-install the Java support, if your database needs it, but I have not tested this yet.

  1. Start SQL*Plus and log in as ‘sys’ to the database
  2. In SQL*Plus execute the following (ofcourse, use your own Oracle HOME path here):
    1. @D:\Oracle\ora81\javavm\install\rmjvm.sql
    2. @D:\Oracle\ora81\rdbms\admin\catalog.sql
    3. @D:\Oracle\ora81\rdbms\admin\catproc.sql
    4. @D:\Oracle\ora81\rdbms\admin\catexp.sql
    5. @D:\Oracle\ora81\rdbms\admin\utlrp.sql
  3. Stop and start your Oracle 8i database (I just used Oracle’s DBA Studio for this)

Rant / Conclusion:

Why does Oracle make me feel so…. ‘old-skool‘? Every Oracle-delivered tool to ‘administrate’ their database:

  1. Starts slowly, very slowly or just delivers a plain shell-like interface
  2. Their user interface tools do not conform to any User Interface Design guideline I have ever seen. Ever!
    1. I mean: I know it’s Java, I know it can look different and even more ugly if you really want it to. Though I have seen Java front-end applications that look and behave like you would expect them to.
    2. If you make a command-line interface, at least include some user-friendly support in it: Not being able to scroll back with the cursor (only with backspace), not being able to select text with the keyboard, not being able to get previously entered commands back… I mean, come on! It’s almost surprising you can copy and paste with this beast.
  3. Even TOAD, which seems to be the only ‘real’ alternative out there, while still being coded in Delphi by the way, is a commercial tool you have to pay for, if you want all the (so needed) features. That the license costs of Oracle do not even get you a normal DBA tool says enough for me. On a side note, though only user interface related: even TOAD makes me feel old-skool.

As the last line in this blog post, one positive comment:

At least Oracle knows how to make a fast database, if you configure and install it properly!


Preventing ‘Page 500’ errors with Drupal on www.mijndomein.nl

2009/09/08

This is a short post: http://www.mijndomein.nl is a cheap shared hosting provider. And as each shared hosting provider goes, they won’t allow specific settings in your .htaccess file. No problem, just that they won’t mention anywhere *what* they don’t allow. And the helpdesk is of no use in the middle of the night. So, here’s the solution:

  • In /.htaccess (so that’s in the root of your Drupal site) comment out the line that says ‘Options +FollowSymlinks’ (thanks to Ewout, below in the comments, for this correction)
  • in /sites/default/files/.htaccess do exactly the same.

Believe it or not, it works beautifully! See http://www.avalizas.com for the result 😉 Which is a shameless plug for the site of my sister and her husband, who just emigrated to Uruguay to start a new life there. Just look at the pictures on that site, that they actually made themselves. Isn’t internet great?

(PS: While I’m on the Drupal subject: May I recommend ‘Boost’ which saved an earlier project for me (http://www.civitas-advies.nl) ? It renders each page for an anonymous user as a ‘static’ page in it’s cache, making PHP-heavy pages being served to the visitor almost instantly!


Transparent proxy for NTLM authentication

2009/09/08

At my work, I am behind a NTLM proxy. No problem with IE, Firefox etc. as they support the NTLM authentication mechanism. But, when using ‘open source’ tools, supporting only basic proxy authentication, like Ruby’s GEM, I was not able to connect to the internet. After some research, I found the solution: Use the open source Squid as a Windows service running a local proxy, and let Squid connect to our company’s NTLM proxy server.

Installing and configuring Squid

Download Squid 2.7 STABLE 6
Extract the archive to C:\Squid (so you’ve got C:\Squid\bin etc. after extracting)
In C:\Squid\etc rename the *.conf.default to *.conf.
Create a directory C:\Squid\var\cache
Edit C:\Squid\etc\squid.conf and replace the contents with this:

#==============================================================================
# SQUID CONFIGURATION FILE FOR TRANSPARENT NTLM PROXY
#==============================================================================
# With this Squid configuration file, you can let any 'basic proxy'-supporting
# application access the internet when you're behind a NTLM authenticating
# proxy server, since this authentication mechanism is not supported by many
# open source tools (think Ruby's GEM, wget, etc.)

#Here the connection to the 'parent' NTLM proxy is specified
#Replace 11.12.13.14 with the IP address of your NTLM proxy
#Replace 8080 with the port of your NTLM proxy
#Optionally, use 'ping proxy' to get the IP address of your proxy server
#Replace login= with your NTLM username and password. Remember to use %20 where a space would be used!
cache_peer 11.12.13.14 parent 8080 0 no-query proxy-only login=user%20name:password

#The port this basic proxy will run on (3128)
http_port 127.0.0.1:3128

#Generic settings for Squid, not touched for the most part
acl all src all
acl manager proto cache_object
acl localhost src 127.0.0.1/32
acl to_localhost dst 127.0.0.0/8
acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
icp_access allow localnet
icp_access deny all
hierarchy_stoplist cgi-bin ?
cache_dir ufs c:/squid/var/cache 100 16 256
access_log c:/squid/var/logs/access.log squid
cache_log c:/squid/var/logs/cache.log
cache_store_log none
mime_table c:/squid/etc/mime.conf
pid_filename c:/squid/var/logs/squid.pid
unlinkd_program c:/squid/libexec/unlinkd.exe
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
acl shoutcast rep_header X-HTTP09-First-Line ^ICY.[0-9]
upgrade_http0.9 deny shoutcast
via off
acl apache rep_header Server ^Apache
broken_vary_encoding allow apache
icp_port 0
htcp_port 0
log_icp_queries off
never_direct allow all
forwarded_for off
client_db off
coredump_dir c:/squid/var/cache

#Restrict who can access the proxy here!
#(Probably better to replace line below with http_access allow localhost
http_access allow all
icp_access allow localnet
icp_access deny all

#Make yourself anonymous with these calls
header_access From deny all
header_access WWW-Authenticate deny all
header_access Link deny all
header_access Warning deny all
header_access Via deny all
header_access User-Agent deny all
header_access Proxy-Connection deny all
header_access X-Forwarded-For deny all
httpd_suppress_version_string on

Open a command prompt
CD to “C:\Squid\sbin”
run “squid.exe -z” to create the needed cache directories and swap files
run “squid.exe -i” to install squid as a system service

run “services.msc” to start the Services Control Panel
Find the “Squid” service and start it (or just type “net start squid”)

Accessing the internet via Squid
In your browser, select “localhost” and port “3128” to connect to the internet via your new squid proxy

If no connection can be established, check “C:\Squid\var\logs\cache.log” to check what possibly went wrong. Fix the parameters in the squid.conf file and restart the service until it works.

For Ruby GEM, for example, add a environment variable “HTTP_PROXY” with value “http://localhost:3128&#8221; (or just use the SET command to test it temporarily)

Encrypting your traffic
Download JAP


Using XSD.exe in VB.NET projects

2009/04/16

XSD.exe, included with the MS SDK, can do a lot. Just search on google. I use it to convert a XSD to a .NET class wrapper.

The problem: Collections of elements are implemented as a standard array(). This means, reading out XML data is easy using the class wrapper, but adding / removing elements to the array is a problem.

Read the rest of this entry »