Categories: , ,
Posted by: bjb

I want to put rounded borders on a stretchy box — expandable vertically and horizontally. I searched the web for solutions to this using pure CSS and found … none.

All the solutions I found had some kind of drawback. They all require you to either have a non-stretchy box in at least one dimension, or they require that your corner graphics be non-transparent. I’m not interested in the solutions that require javascript. The javascript just adds HTML elements or changes the CSS, anyway. And it’s slower than pure HTML and CSS, and sometimes people turn off javascript. Heaven forbid that they should miss out on the rounded corners.

The non-stretchy solutions involve having a single graphic to cover two or more corners — making stretching in the dimension between the two corners impossible.

There are a few non-transparent solutions that allow you to have a stretchy box. The solutions are various ways of stretching the sides of the box out to the corners, and then putting corner graphics on top of the sides. Thus the requirement to have opaque corners. One method is the sliding doors, another the Russian doll divs, and there are more as well.

One solution uses the pseudo-elements :before and :after, which is not supported in MSIE. Unfortunately, some people who read my blog (there are one or two people) use MSIE and complain when my blog looks funny. And they won’t switch browsers (or OSs, too bad).

Some solutions to the rounded-corners problem require you to have a certain set of elements in your html structure on which to place the corner and side graphics, and then claim that the solution does not require extraneous html elements. But if you don’t want a header element or a definition list in your box, you’re out of luck for that solution.

But I want stretchy sides and transparent-background corners around arbitrary contents.

Given that in order to implement this, I’m going to have to introduce extra HTML elements anyway, I think it is worth mentioning that a table can do what I want. A three by three table, with narrow fixed-width first and third columns and rows will allow the middle cell to stretch to accomodate its content. The first and third column and row cells can each have a different background image and each image displays in its own space with no overlap, allowing for transparent backgrounds in the graphics. Or, if you don’t want to have to maintain the table column and row widths and heights in sync with the graphics, you can put the graphics into those cells as HTML elements. Hey, one method is as evil as the other.

So, sometimes I’m going to use tables in my HTML. It is the best possible solution for this problem at this time. I sure hope HTML 5 has some sensible help for layout.

Categories:
Posted by: bjb

The first beam:

Image IMG_3547-med.JPG Image IMG_3548-med.JPG Image IMG_3549-med.JPG

Preparing for the second beam, at right angles to the first:

Image IMG_3551-med.JPG Image IMG_3552-med.JPG Image IMG_3553-med.JPG

The second beam is up, they are adjusting its position with a sledgehammer:

Image IMG_3557-med.JPG

Connect the two beams:

Image IMG_3559-med.JPG Image IMG_3560-med.JPG

Take out a temporary wall:

Image IMG_3656-med.JPG Image IMG_3657-med.JPG

The view without the temporary wall:

Image IMG_3658-med.JPG Image IMG_3727-med.JPG Image IMG_3730-med.JPG

Categories:
Posted by: bjb

Here’s the replacement for the load-bearing walls (see the nice red beams up near the ceiling). John put wood 2x6 along the bottom of the beam in order to have something to attach to while doing the rest of the finishing.

Image

Categories: , , ,
Posted by: bjb

I apt-get upgraded, and then apt-get using apt-cacher didn’t work any more. It seems if you have a perl IPv6 library installed (IO::Socket::INET6), apt-cacher will assume you have deployed IPv6 and it will make an IPv6 only connection for listening.

To make all your services obtain IPv4 address along with IPv6 ones, as root “echo 0 > /proc/sys/net/ipv6/bindv6only” and edit /etc/sysctl.d/bindv6only.conf to contain 0 rather than 1. Then restart your service(s).

Or if you do have IPv6 running locally, you can change your apt sources.list file (/etc/apt/sources.list) to refer to ipv6-localhost instead of localhost:

deb     http://ip6-localhost:3142/debian.mirror.iweb.ca/debian/ unstable main contrib non-free
deb-src http://ip6-localhost:3142/debian.mirror.iweb.ca/debian/ unstable main contrib non-free

(other distro’s might use another name like localhost6. Look in your /etc/hosts file for the right name.)

Another gotcha: If you install apt-cacher-ng, and you already have apt-cacher running, then apt-cacher-ng will attach to the remaining free interface (the IPv4 one) and apt-cacher will still be running on IPv6. The two packages don’t conflict. Yeargh. I can’t wait to see the cache corruption … Ah, no cache corruption. It starts its own cache — from scratch. Well better that than corruption I guess. But, even better to be running only one of them on all listening ports.

And another gotcha: Installing apt-cacher-ng might end up adding a proxy config to your apt config like so:

/etc/apt/apt.conf:  Acquire::http::Proxy "http://aa.bb.cc.dd:3142";

so then if you use urls as above, you would have specified the proxy twice: once in the url and once in the apt.conf file. Apt then complains with:

Failed to fetch http://aa.bb.cc.dd:3142/volatile.debian.org/debian-volatile/dists/lenny/volatile/contrib/source/Sources.gz  403  URL seems to be made for proxy but contains apt-cacher-ng port. Inconsistent apt configuration?

The fix is to remove the proxy either from apt.conf or from the sources.list entries. Note that the proxy might have been put in /etc/apt/apt.conf.d/01proxy or something like that instead.

Well that was a lot more exciting than I’d hoped for.

Categories: , , ,
Posted by: bjb

The exim4 config file is a bit annoying because it is hard to know what statements are assignments and what statements are conditions. Below, the debug_print, driver, and data statements (in the hub_user route) are assignments, while the domains and check_local_user statements are conditions. Note how the config file designer helpfully mixed them together.

hub_user:
  debug_print = "R: hub_user for $local_part@$domain"
  driver = redirect
  domains = +local_domains
  data = ${local_part}@DCreadhost
  check_local_user

hub_user_smarthost:
  debug_print = "R: hub_user_smarthost for $local_part@$domain"
  driver = manualroute
  domains = DCreadhost
  transport = remote_smtp_smarthost
  route_list = * DCsmarthost byname
  host_find_failed = defer
  same_domain_copy_routing = yes
  check_local_user
.endif

Anyway, to help with debugging exim4 routers, you can use the -bt option to exim4:

blueeyes:~# exim4 -bt bjb bjb@localhost bjb@blueeyes
R: system_aliases for bjb@linuxbutler.ca
R: userforward for bjb@linuxbutler.ca
R: procmail for bjb@linuxbutler.ca
bjb@linuxbutler.ca
  router = procmail, transport = procmail_pipe
R: system_aliases for bjb@localhost
R: userforward for bjb@localhost
R: procmail for bjb@localhost
bjb@localhost
  router = procmail, transport = procmail_pipe
R: system_aliases for bjb@blueeyes
R: userforward for bjb@blueeyes
R: procmail for bjb@blueeyes
bjb@blueeyes
  router = procmail, transport = procmail_pipe
blueeyes:~# 

Note to self: “satellite” mail type is for machines whose mail is forwarded to another machine. Use “smarthost” for machines on which I actually read mail.

Categories: , , ,
Posted by: bjb

Handy quick conversion for timestamps in Nagios or unix logs: time.localtime (time.time);

eg:

bjb@bjb-pc:~/work/redmine/redmine-abitibi/app/views/mailer$ python
Python 2.5.2 (r252:60911, Jan 24 2010, 17:44:40)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.time
<built-in function time>
>>> time.time ()
1284568746.503253
>>> time.localtime (1284523200)
(2010, 9, 15, 0, 0, 0, 2, 258, 1)
>>> time.localtime (1284520137)
(2010, 9, 14, 23, 8, 57, 1, 257, 1)
>>> 
Categories: ,
Posted by: bjb

Both before and after upgrading byteflow to use django 1.2, one thing that wasn’t working is postimage. The most recent problem was the link to post an image (in the admin page for creating or editing a blog post) was completely missing (whereas before it was present but malfunctioned).

The reason it was missing was that the javascript to create that link, in static/js/postimage.js, failed on line 42, in the showLinkFor function. It failed on

elem.previousSibling.appendChild(document.createElement('br'));.

I fixed it by inserting the link before the blog text instead of after the previous node’s contents:

    //  showLinkFor: function(elem) {
    //      elem.previousSibling.appendChild(document.createElement('br'));
    //      elem.previousSibling.appendChild(this.getLink(elem.id));
    //  },

    showLinkFor: function(elem) {
        var parent = elem.parentNode;
        var mybr = document.createElement('br');
        var myid = this.getLink(elem.id);
        parent.insertBefore (myid, elem);
        parent.insertBefore (mybr, elem);
    },

I have a non-standard URL_PREFIX of bjb/ and postimage didn’t play nice with that. I hard-coded my URL_PREFIX into the postimage.js file:

    getLink: function(id) {
        var link = document.createElement('a');
        link.setAttribute('href', '/bjb/admin/postimage/attach/?for=' + id);
        ...

Not elegant, but it got me past that problem. The next problem was that the list of files was empty. I set the POSTIMAGE_ROOT to point to a directory on the server machine with pictures in it, and then the list was not empty.

But it wasn’t full of all the pictures in that hierarchy either … that was just a file permission problem (web server couldn’t read some of them).

So now I can use postimage. It doesn’t do quite what I expected. What it does is allow you to choose among pictures on your server for inclusion into your blog. It doesn’t let you preview them. All it does is give you a list of files, and then put a link to the most recently chosen file in your blog text. You can call it over and over and it will add more image links. It looks like it can take the render method into account — there is a choice of markdown, html, rst. But, that choice was in the source code … not sure if it will detect your render method automatically.

I expected to be able to upload pictures to the blog … oh well. I guess the way postimage works is safer. It doesn’t put files up there for you — it assumes you have put them up already — into a “POSTIMAGE_ROOT” directory — and just accesses what is already there.

Categories:
Posted by: bjb

Before:

Image

During (1):

Image

During (2):

Image

During (3):

Image

During (4):

Image

During (5):

Image

Look Ma! No load-bearing walls! … now how do you put this thing back together again ???

Posted by: bjb

I’m trying out byteflow under django 1.2, and I finally have it working. There were only a few changes to make.

First off, the databases are specified differently in django 1.2 — there is the option to connect to multiple databases now. Strangely however, django did not force me to change my database settings … I guess there is some backward compabitility stuff for now.

old settings_local.py

    DATABASE_ENGINE = 'postgresql_psycopg2'
    DATABASE_NAME = 'byteflow'
    DATABASE_USER = 'db_user'
    DATABASE_PASSWORD = 'sekrit'

new settings_local.py

    DATABASES = { 'default' :
        {
            'ENGINE' : 'postgresql_psycopg2',
            'NAME'   : 'byteflow',
            'USER'   : 'db_user',
            'PASSWORD' : 'sekrit',
        }
    }

There are also some deprecation warnings in the logs about admin.site.root, in urls.py (I may have added all those ‘settings.BLOG_URLCONF_ROOT’ in when using ‘bjb’ as my URL_PREFIX):

old:
    url(r'^%sadmin/(.*)' % settings.BLOG_URLCONF_ROOT,
        admin.site.root, name='admin'),

new:
    url(r'^%sadmin/(.*)' % settings.BLOG_URLCONF_ROOT,
        include(admin.site.urls)),

But this didn’t work for me so I went back to the old way. The problem was that when I asked to edit a blog post, it brought me to the main admin page. When I clicked on the Change link, it stayed on the main admin page. I’ll have to look into that another time.

An update was required to apps/tagging/managers, in usage_for_queryset, to update the database query for the django 1.2 database scheme (multiple databases). I found this hint.

Also, in order to run django 1.2 on my stable machine, I set up a virtualenv (with --no-site-packages) in which to run it. Had to install all the site-packages into the virtualenv:

  • BeautifulSoup-3.1.0.1
  • Django-1.2.1
  • PIL
  • mx
  • openid
  • psycopg2-2.0.7

That’s about it except for infrastructure:

  • easy-install
  • pip-0.8
  • setuptools-0.6c8

Well I suppose I should have started by upgrading byteflow, I’ll have to try that another time. Maybe some of my changes have been fixed in upstream already. However I did quickly note that the byteflow install page still says it requires django 1.0.

Categories:
Posted by: bjb

If you want to do some unattended operations on your postgres database, and if you haven’t specified that the user who will do those unattended operations has access to that database using ident or sameuser authorization in /etc/postgresql/M.N/main/pg_hba.conf, then you will have to give a password upon invocation. But, postgres commands generally don’t let you specify a password on the command line (and there is a good reason for this).

There are two ways to configure your admin user to be able to work on your postgres database. One is with an environment variable and the other is with a postgres password config file in the admin user’s home directory.

The environment variable to set is PGPASSWORD, for example export PGPASSWORD=sekrit; pg_dump mydatabase.

The config file method means writing lines like hostname:port:database:username:password into a file called .pgpass in the admin user’s home directory. Don’t forget to set the permissions on ~/.pgpass to 0400, or -r--------.

The reason why postgres strongly discourages specifying the password on the command line is that it is easy for other users on the system to see that password with a simple invocation of the ps command.