6
I Use This!
Activity Not Available

News

Analyzed 6 months ago. based on code collected 6 months ago.
Posted about 15 years ago by Liraz Siri
I just finished upgrading the WYSIWYG editor on the web site from FCKEditor to CKEditor, which is FCKEditor's less offensively named successor. Improvements A noticeably faster, more lightweight code-base which was rewritten from ... [More] the ground up. Full-screen mode works beautifully now. I love how this instantly removes all the clutter and lets me focus on the content I'm editing without being distracted by the rest of the web site. The edit area can be resized dynamically by dragging the window corner, giving you as much room to edit as you need. If you've ever felt uncomfortably cramped inside a tiny edit box you know what a relief it can be to escape. Source mode now pretty prints your XHTML tags, with proper indenting. When you need to edit raw source, this feature makes it much easier to visually parse what you're looking at. A status field provides information showing your current position in the document's tag hierarchy. Advanced theming support. The new default theme Kama let's you pick a colorset to match the theme of your web site: Personally I like Kama better but if you're feeling attached to FCKeditor's somewhat clunky looks you can select CKEditor's V2 theme which looks just like it: Out of the box CKEditor also comes with a rather pretty Office 2003 theme: Drupal installation and upgrade notes On Drupal, you install CKEditor the same way you install FCKEditor. First you download CKEditor and the CKEditor Drupal module. Next, extract the CKEditor Drupal module in your site modules directory and then extract CKEditor itself into the module's directory, like this: cd /etc/drupal/6/sites/all/modules tar -zxvf ckeditor-6*.tar.gz mv ckeditor_3* ckeditor cd ckeditor tar -zxvf ckeditor_3* Enable the CKEditor module while disabling FCKEditor (I.e., enabling both will result in Javascript errors). Drupal's CKEditor module inherits the settings from the FCKEditor module so the upgrade is relatively painless. If you've customized FCKEditor's button layout by editing modules/fckeditor/fckeditor.config.js you'll want to customize CKEditor's button layout as well by editing the profiles in modules/ckeditor/ckeditor.config.js. Most of the button names are the same except for a handful which have been renamed: FormatName => Format FontFormat => Font UnorderedList => BulletedList OrderedList => NumberedList StrikeThrough => Strike Rule => HorizontalRule Gotcha: pop-up mode is broken (but good riddance!) FCKEditor was slow enough that we decided to disable it by default for administrator accounts on this web site while still allowing us to launch it on demand in a pop-up when we really needed it. The bad news is that pop-up mode doesn't work well in the version of CKEditor I've been testing so I've had to disable it. The good news is that CKEditor is fast enough now that I can enable it by default and the full-screen mode works even better for minimizing distractions. Come to think of it, pop-up mode in FCKEditor was kind of a disaster. If you accidentally tried opening more than one editing pop-up, you would loose loose your previous edit without warning. After that happened a few times I developed a deep mistrust for FCKeditor and would edit the bulk of my content without it. Good riddance to that! [Less]
Posted about 15 years ago by Alon Swartz
Keeping it simple, HTTPS is a combination of the HTTP and SSL/TLS protocols, which provides encryption and identification of the server.  The main idea is to create a secure channel over an insecure network, ensuring "reasonable" protection from ... [More] eavesdroppers and man-in-the-middle attacks. The trust inherent in HTTPS is based on the inclusion of "trusted" Certificate Authority (CA) certificates pre-installed in web browsers.  Basically, if your SSL certificate is not signed by one of these CA's, the browser will display a warning. TurnKey appliances generate self signed certificates on firstboot to provide an encrypted traffic channel, but because the certificates are not signed by a trusted CA, the warning is displayed. In most cases, this is acceptable. If it's not, go get an signed certificate. Authoritatively signed certificates Cost Authoritatively signed certificates can be costly, for example, Verisign (the most well known CA) charges $1,499 per year for their recommended certificate. There are cheap alternatives (I recently purchased a certificate from Go Daddy for $12.99) as well as a couple of free providers. Generate key and CSR First up is to create a certificate key and a certificate signing request (CSR). This can be done with OpenSSL. apt-get update apt-get install openssl # replace bold type with your info openssl req -new -newkey rsa:2048 -nodes -out www_example_com.csr -keyout www_example_com.key -subj "/C=US/ST=Arizona/L=Scottsdale/O=Example Company Inc./CN=www.example.com" Submit the CSR The above will generate two files, www_example_com.key and www_example.com.csr. Once you have signed up for an authoritatively signed certificate, you will be requested to upload the CSR file or its contents. Verify the request The signing authority will need to verify the validity of the request and that it was submitted by the entity to which the domain in the request is registered, usually done by contacting the administrative contact for the domain. Further steps may be required when requesting an Extended Validation (EV) certificate, which color the address bar green in recent browsers. Download signed certificate After validation, your signed certificate (crt) will be available for download. Most likely your signing authority will include an intermediate CA certificate bundle (trust chain). Note: you should make a backup of all SSL related files. Generate PEM and placement Generate the pem from the key and crt cat www_example_com.key www.example.com.crt > cert.pem Place the generated pem and intermediate bundle (eg. bundle.crt) in /etc/ssl/certs/, and make them read-only to root. chown root:root *.pem *.crt chmod 400 *pem *.crt Update configuration, enable SSL and reload webserver Apache configuration <VirtualHost *:443> SSLEngine on SSLCertificateFile /etc/ssl/certs/cert.pem SSLCertificateChainFile /etc/ssl/certs/bundle.crt </VirtualHost> a2enmod ssl /etc/init.d/apache2 force-reload Lighttpd configuration /etc/lighttpd/conf-available/10-ssl.conf $SERVER["socket"] == "0.0.0.0:443" {     ssl.engine  = "enable"     ssl.pemfile = "/etc/ssl/certs/cert.pem"     ssl.ca-file = "/etc/ssl/certs/bundle.crt" } lighty-enable-mod ssl /etc/init.d/lighttpd force-reload Do you use an authoritatively signed certificate? Is self-signed sufficient? Leave a comment! [Less]
Posted over 15 years ago by Liraz Siri
Psssst. Hey you... yeah you. Word on the street is your shell scripts don't do any error handling. They just chug happily along even when everything is broken. Because a lowly shell shell script doesn't need any error handling right? WRONG! ... [More] <!--break--> Here are two simple tricks that are easy to use and will make your scripts much more robust. Turn on -e mode (do you feel lucky - punk?) In this mode any command your script runs which returns a non-zero exitcode - an error in the world of shell - will cause your script to itself terminate immediately with an error. You can do that in your shebang line: #!/bin/sh -e Or using set: set -e Yes, this is what you want. A neat predictable failure is infinitely better than a noisy unreliable failure. If you REALLY want to ignore an error, be explicit about it: # I don't care if evil-broken-command fails evil-broken-command || true Oh and as long as you're messing with shell modes, -e goes well with -x (which I like to think of as shell X-ray). Like this: #!/bin/sh -ex Or like this: # turn -x on if DEBUG is set to a non-empty string [ -n "$DEBUG" ] && set -x That way you can actually see what your script was doing right before it failed. Use trap for robust clean-ups A trap is a snippet of code that the shell executes when it exits or receives a signal. For example, pressing CTRL-C in the terminal where the script is running generates the INT signal. killing the process by default generates a TERM (I.e., terminate) signal. I find traps most useful for making sure my scripts clean-up after themselves whatever happens (e.g., a non-zero error code in -e mode). For example: #!/bin/sh -e TMPFILE=$(tempfile) trap 'echo "removing $TMPFILE"; rm -f $TMPFILE' INT TERM EXIT echo TMPFILE=$TMPFILE echo hello world > $TMPFILE cat $TMPFILE # gives user a chance to press CTRL-C sleep 3 # false always returns an error false echo "NEVER REACHED" Note that you can only set one trap per signal. If you set a new trap you're implicitly disabling the old one. You can also disable a trap by specifying - as the argument, like this: trap - INT TERM EXIT [Less]
Posted over 15 years ago by Liraz Siri
Open source virtualization has been evolving dramatically over the last few years. Incumbent proprietary platforms such as VMWare still hold the throne in many areas but open source competitors are gaining ground fast on their way to ubiquity. Things ... [More] are a-changing in the land of virtualization. Right now we have three contenders to the (open source) throne battling it out for supremacy: Xen: backed by Citrix VirtualBox: backed by Oracle/Sun KVM: backed by RedHat <!--break--> Neither Citrix nor Oracle have yet to establish a good track record with regards to open source so I recently took the time to dig a little deeper into KVM and qemu, two projects which I suspect are going to be a huge part of the future of open source virtualization. KVM: at its essence KVM is just a kernel infrastructure. It's not a product. The developers forked qemu to hook into the KVM kernel infrastructure and take advantage of it. Eventually the fork was merged back into the qemu mainstream. qemu: powers nearly all Linux virtualization technologies behind the scenes. Qemu is a spectacular piece of software written largely by Fabrice Bellard, a programming genius who also wrote TCC (tiny c compiler), FFMpeg and many other less famous programs. Highlights from my findings: I'm pretty sure KVM is the future of open source virtualization. Not Xen or VirtualBox. KVM is a latecomer to the virtualization game but its technical approach is superior and many believe it will win out eventually over other virtualization technologies and become the transparent virtualization standard of the future. Personally, I think that's a pretty likely outcome at this point. The primary advantages going for KVM is simplicity and leverage. By taking advantage of the hardware-level support in new processors, KVM can be many times simpler than competing technologies such as Xen or VMware while achieving equivalent or superior performance. KVM leverages the Linux kernel in a way that allows its developers to focus their resources more efficiently on actual virtualization related development. The proof is in the pudding. With just a fraction of the resources their competitors have, the KVM implemented advanced features such as live migration, and SMP support (e.g., up to 255 virtual CPUs regardless of how many CPUs the host has). Even recursive virtualization should be possible (I know patches were written to get it to work). libvirt: Redhat are spearheading development of a backend-agnostic management layer for virtualization (libvirt). The fundamental design is pretty good, but for our purposes (I.e., TurnKey development) libvirt and its higher-level friends just get in the way. The really useful parts are the qemu-based primitives, which are easier to use directly than through the libvirt stuff. qemu supports multiple mechanisms for plugging guest NICs together - via a TCP/UDP port, attaching to a tap/tun device or even plugging into VDE (virtual distributed ethernet), which allows arbitrarily complex virtual network topologies to be constructed that span multiple physical machines. I've played around with a few test configuration and it's pretty neat. Qemu vs VirtualBox Though it's hard to tell, VirtualBox was forked from an earlier version of qemu. The main thing VirtualBox added was sophisticated binary recompilation that allowed fast virtualization without requiring support from the underlying hardware. Today most modern PC processors from Intel and AMD have hardware support for virtualization which makes binary recompilation techniques unnecessary. This allows hypervisors such as KVM to achieve the same results using a simpler hardware-enabled approach with superior performance. VirtualBox also added a user-friendly GUI shell that simplifies setting up virtual machines in a desktop environment. In general, I was favorably surprised by qemu. If VirtualBox is the notepad of open source virtualization. Qemu is Vim. In other words if you're looking for a swiss-army virtualization knife you can get hacking at, qemu beats VirtualBox many times over. Random insights: Qemu has equivalent-better performance with KVM If your hardware can't support KVM, then performance won't be as good as VirtualBox but if you use the KQEMU kernel acceleration module, it will be acceptable (e.g., on my system 30 seconds with KQEMU to boot lamp vs 20 seconds in KVM node) Qemu is a better primitive than VirtualBox: Good defaults are chosen if you don't specify otherwise It's simpler to launch VMs from the cli: qemu -cdrom appliance.iso # install appliance.iso to test.img qemu-img create /virtdisks/test.img 4G qemu -cdrom appliance.iso -hda /virtdisks/test.img Supports launching VMs as detached daemon processes Supports VNC graphics mode with optional encryption and authentication Easier to script Supports a scriptable VM monitor Can work without root privileges, unless you want to use tap/tun interfaces Also, it wouldn't be too complicated to write a wrapper that allows users to safely run qemu + tap/tun without root privileges. Easy to use default usermode networking built-in NAT, dhcp, tftp host can be accessed by guest on 10.0.2.2 supports forwarding host ports to guest (-redir option) Qemu can boot 64bit guests on a 32bit host using processor emulation. I tried this and it works, though its pretty slow: qemu-system-x86_64 -cdrom ./lenny-amd64-standard.iso Qemu can be configured to allow transparent chrooting into non-native chroots without launching a VM (e.g., chroot into a 64bit debootstrap from a 32bit system) Its a bit tricky and the default Ubuntu package doesn't yet include the Debian patches that enable this very neat trick. For usage scenarios where cli usage isn't optimal, you can use one of several GUI front-ends written for qemu. I liked qemuctl and qemu-launcher (for different purposes).   [Less]
Posted over 15 years ago by Alon Swartz
Each Amazon EC2 instance has associated metadata, as well as user data supplied when launching the instance. The meta and user data is instance-specific, and therefore only accessible to the instance. The data is useful on several levels, such as ... [More] configuring SSH public keys, programmatically configuring the instance according to certain criteria, or even executing user supplied initialization scripts.   Retrieving the data Retrieving the data is done by querying an Amazon web server with the base URI of http://169.254.169.254/API-VERSION. The available API versions can be queried by performing a GET request on http://169.254.169.254/. The latest version of the API is always available using the URI http://169.254.169.254/latest. There is quite a lot of information available through the API, some more useful than others. For example, ami-id, ami-launch-index, availability-zone, instance-id, public-ipv4, user-data, ... (see below for the full list). Some notes on user data One of the most useful pieces of data is user-data, which can be used to pass configuration information or even initialization scripts to the instance upon launch. User data must be base64 encoded, and is limited to 16k (pre-encoding).  The popular API tools usually handle the encoding transparently, so you shouldn't have to worry about it. The data is also decoded before presented to the instance, so again, you shouldn't need to worry. What you do need to worry about though, or at least be aware of, is security. The user-data (and all metadata for that matter) can be accessed by any user or process on the instance. So please, please, do not specify any secret information in user-data unless you are absolutely sure what you are doing. Even then, I'd think twice. But, you say, I trust all my users and processes. OK, how about this (thanks go to Eric Hammond for this example). You run a website that allows users to upload files by specifying a URL. The user specifies http://169.254.169.254/latest/user-data, and lo-and-behold, your user-data and any secrets included have been divulged. Do you still want to include secrets in user-data? The simple way The simplest way of retrieving metadata is by use of a command line network tool, such as curl, for example: curl http://169.254.169.254/latest/meta-data/public-ipv4 The more programmatic way Usually you need a more programmatic type interface, and there are a couple of libraries for different languages available. I didn't find one that met my needs, so I wrote one in Python called ec2metadata.py. I licensed the copyright over to Canonical so it could be included in Ubuntu's ec2-init package. ec2metadata.py has a CLI interface, as well as a Pythonic interface: $ ec2metadata.py # all options will be displayed $ ec2metadata.py --instance-id # displays the instance id import ec2metadata instanceid = ec2metadata.get('instance-id') print instanceid It can be very useful when coupled with inithooks, for example, setting of the SSH public keys on first boot. #!/usr/bin/python # # Query and display EC2 metadata related to the AMI instance # Copyright (c) 2009 Canonical Ltd. (Canonical Contributor Agreement 2.5) # # Author: Alon Swartz <[email protected]> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. """ Query and display EC2 metadata If no options are provided, all options will be displayed Options: -h --help show this help --kernel-id display the kernel id --ramdisk-id display the ramdisk id --reservation-id display the reservation id --ami-id display the ami id --ami-launch-index display the ami launch index --ami-manifest-path display the ami manifest path --ancestor-ami-id display the ami ancestor id --product-codes display the ami associated product codes --availability-zone display the ami placement zone --instance-id display the instance id --instance-type display the instance type --local-hostname display the local hostname --public-hostname display the public hostname --local-ipv4 display the local ipv4 ip address --public-ipv4 display the public ipv4 ip address --block-device-mapping display the block device id --security-groups display the security groups --public-keys display the openssh public keys --user-data display the user data (not actually metadata) """ import sys import time import getopt import urllib import socket METAOPTS = ['ami-id', 'ami-launch-index', 'ami-manifest-path', 'ancestor-ami-id', 'availability-zone', 'block-device-mapping', 'instance-id', 'instance-type', 'local-hostname', 'local-ipv4', 'kernel-id', 'product-codes', 'public-hostname', 'public-ipv4', 'public-keys', 'ramdisk-id', 'reserveration-id', 'security-groups', 'user-data'] class Error(Exception): pass class EC2Metadata: """Class for querying metadata from EC2""" def __init__(self, addr='169.254.169.254', api='2008-02-01'): self.addr = addr self.api = api if not self._test_connectivity(self.addr, 80): raise Error("could not establish connection to: %s" % self.addr) @staticmethod def _test_connectivity(addr, port): for i in range(6): s = socket.socket() try: s.connect((addr, port)) s.close() return True except socket.error, e: time.sleep(1) return False def _get(self, uri): url = 'http://%s/%s/%s/' % (self.addr, self.api, uri) value = urllib.urlopen(url).read() if "404 - Not Found" in value: return None return value def get(self, metaopt): """return value of metaopt""" if metaopt not in METAOPTS: raise Error('unknown metaopt', metaopt, METAOPTS) if metaopt == 'availability-zone': return self._get('meta-data/placement/availability-zone') if metaopt == 'public-keys': data = self._get('meta-data/public-keys') keyids = [ line.split('=')[0] for line in data.splitlines() ] public_keys = [] for keyid in keyids: uri = 'meta-data/public-keys/%d/openssh-key' % int(keyid) public_keys.append(self._get(uri).rstrip()) return public_keys if metaopt == 'user-data': return self._get('user-data') return self._get('meta-data/' metaopt) def get(metaopt): """primitive: return value of metaopt""" m = EC2Metadata() return m.get(metaopt) def display(metaopts, prefix=False): """primitive: display metaopts (list) values with optional prefix""" m = EC2Metadata() for metaopt in metaopts: value = m.get(metaopt) if not value: value = "unavailable" if prefix: print "%s: %s" % (metaopt, value) else: print value def usage(s=None): """display usage and exit""" if s: print >> sys.stderr, "Error:", s print >> sys.stderr, "Syntax: %s [options]" % sys.argv[0] print >> sys.stderr, __doc__ sys.exit(1) def main(): """handle cli options""" try: getopt_metaopts = METAOPTS[:] getopt_metaopts.append('help') opts, args = getopt.gnu_getopt(sys.argv[1:], "h", getopt_metaopts) except getopt.GetoptError, e: usage(e) if len(opts) == 0: display(METAOPTS, prefix=True) return metaopts = [] for opt, val in opts: if opt in ('-h', '--help'): usage() metaopts.append(opt.replace('--', '')) display(metaopts) if __name__ == "__main__": main()   [Less]
Posted over 15 years ago by Liraz Siri
While reading CSS books and experimenting I found it helpful to take notes and put together a cheat sheet for quick reference. I figured others might find it useful so I'm sharing. I've also uploaded a simple PDF version. <!--break--> ... [More] Selectors Basic h1 select all <h1> tags h1.special select h1 tags of the special class h1#special select h1 tags of special id p a select <a> tags descendant from p h1, h2 select both h1, h2 * select all tags implicit in .class = *.class #class = *#class #banner * select all tags inside banner a:link selects link that guest hasn't visited regular style a:visited link that visitor has clicked before a:hover link when mouse is hovered over a:active link when it's clicked (just a ms) .class1.class2 select elements that have both class1 and class2 Pseudo-classes generate content :before inserts content before p.tip:before {content: "HOT TIP!" } :after like :before but after properties generated pseudo-classes can be styled like any other display color border content string content: "(link) " urls content: url(path/to/image) attributes content: attr(href) combinations content: " [" attr(href) "]" :first-child select and format just the first child of an element e.g., li:first-child { font-weight: bold; } formats all first elements in bold :focus when element receives focus (e.g., click or tab) e.g., input:focus { background-color: #FFFFCC; } Advanced selectors child selectors body > h1 select any h1 that is a child of body adjacent siblings h2 + p select p right after h2 attribute selectos img[title] select only img tags with "title" attribute .photo[title] select any element with photo class and a title attribute input[type="text"] input fields of type text a[href][title] select a that has both href and title attrs *[title] any element that has title attribute img[title~="Figure"] any img with title that contains Figure in it regexp match? img[title^="bar"] any img with title that starts with "bar" img[title$="bar"] any img with title that ends with "bar" img[title*="bar"] any img with title that contains substring "bar" *[lang|="en"] any element with lang attr that equals en begins with en- Pseudo-classes :first-line :first-letter just the first letter can only be applied to block elements (not inline) Psuedo-elements :before :after # examples h2:before {content: "]]"; color: silver;} body:after {content: " The End.";} Floats containing block nearest block-level ancestor floated element generates a block box regardless of its type will be laid out as a float Rules stay within borders of containing element left/right outer edge may not be to the left of inner left/right containing block. give precedence to existing floats prevent floats from overwriting each other floats are safe left outer edge must be to the right of the right outer edge of a preceding element. no overlapping between float elements if they collide the loosing element will be floated down can't be higher than inner top (pre-padding) of containing parent floats can't be higher than the tops of preceding floats If we have 3 floats, and the first two are floated to the left, the third float will float only as high as the second float. floats can't float higher than the top of the line box generated by a preceding element floats get pushed down to a new line height if there isn't room for them in the containing box given the above constraints, float as high as possible left floating elements try to float as left as possible, right floating elements try to float as right as possible BUT a higher position is preferred to floating more right Rule consequences when floated element is taller than container? the bottom sticks out of the container countermeasure floated element will expand to contain floated descendants negative margins can cause floats to appear to escape their parents just like negative margins on non-floated elements can make the child appear wider than it's parent if floated element is wider than it's parent it can stick out negative margins may cause a float to overlap inline elements inline elements rendered on top of the float a float expands to contain anything in it move to the left or right edge of the browser window (or containing window) floated inline methods are treated like blocks content with a background or border runs underneath the float how to prevent this - overflow: hidden clear property don't wrap around a floated item left - drop below left floated items right - drop below right floated items both - drop below both Positioning position := static | relative | absolute | fixed | inherit static generated as normal relative offset by some distance element retains it's shape space it would ordinarily have occupied preserved absolute removed from the flow positioned with respect to its *containing* block may be another element in the document space the element might have occupied is closed up as if the element didn't exist positioned element generates a block-level box even if it's inline fixed element box behaves like absolute but containing block is the viewport itself containing block in HTML the root element is HTML some browsers use body initial containing block rectangle the size of the viewport nearest ancestor (of any kind) that has position value != static block-level containing ancestor padding edge (I.e., border bounded area) inline-level containing ancestor content edge of the ancestor in ltr lang - top left corner, right bottom corner no ancestors? initial containing block important - elements can be positioned outside containing block maybe it should be called "positioning context" instead offset properties top, right, bottom, left := <length> | <percentage> | auto | inherit percentage containing width for left / right height for top / bottom auto element position if it were static positioning can cause height/width to be calculated automatically e.g., height 100% top: 0 bottom: 0 width 100% left: 0 right: 0 margins apply to the position boundaries you're really specifying the position of the outer edge setting width/height can make a difference IF you set borders, padding, margin because width/height set inner edges the content box fixed position can be used to simulate frames of old just like absolute position except the containing block is the viewport Properties formatting text line-height letter-spacing # how much space to add between letters font-family sans # clean and simple appearance (for headlines) Arial Helvetica Verdana Tahoma Formata Sans serif # better for long passages of text Georgia Times Times New Roman popular combinations Arial, Helvetica, sans-serif "Times New Roman", Times, serif "Courier New", Courier, monospace Georgia, "Times New Roman", Times, serif font size keywords xx-small x-small small medium large x-large xx-large each increase or decreases by 1.2 ems and percentages the same thing font styles font-style: italic|bold|normal text-transform: uppercase font-variant: small-caps text-decoration: underline|overline|line-through|blink spacing attributed letter-spacing word-spacing line-height normal setting is 120% alignment text-align: left|center|right|justify text-indent e.g., text-indent: 3em indent first line 3em text-shadow <color> <offset-x> <offset-y> <blur-radius>? text-shadow: green 5px 0.5em; not supported in Firefox white-space normal | nowrap | pre | pre-wrap | pre-line | inherit normal := discards extra whitespace collapses multiple "spaces" pre := treated as if it's pre whitespace is nog ignored pre-line := whitespace collapsed, linefeeds honored pre-wrap := like pre except lines wrap no-wrap := prevent wrap breaks from being rendered line breaks must be inserted with <br /> lists list-style-type: square|disc|circle list-style-position: outside|inside margins and padding margin: 5px 5px on all sides margin: 5px 1px 5px top and bottom 1px on the sides margins between elements don't get added the larger of the two margins is applied padding is added whenever vertical margins touch the margins collapse inline vs block display: inline|block; inline elements don't get any taller with padding or margins except for img tags colors rgb(30%, 30%, 30%) #FFF #FFFFFF names aqua fuchsia lime olive red white black gray maroon orange silver yellow blue green navy purple teal border each side can have a different property width / height em is the text size percentages = size of containing element max-width min-width max-height min-height width/height do not include borders, padding and margins just the content displayed width = width + left padding + right padding + left border + right border + left margin + right margins height property dangerous because it's hard to know in advance the size of content in a box amount of margins between paragraphs, headlines varies from browser to browser for consistent predictable results set this yourself background images background-image: url(images/bg.gif); url is relative to the stylesheet not the HTML page root relative absolute background-repeat repeat normal setting, repeat both on x and y repeat-x repeat-y no-repeat displays the image a single time background-position precise values <distance-from-left> <distance-from-top> keywords <horizontal> <vertical> <horizontal> := left|center|right <vertical> := top|center|bottom bottom is the bottom of the content not necessarily the bottom of the pag e.g., background-position: left center percentages short hand background := <background-color> <background-image> <background-attachment> <background-position> it's possible to replace borders with hand-drawn lines overflow := hidden | visible | scroll | auto visible - normal setting what browsers usually do scroll - add scroll bars auto - make scroll bars optional hidden - hides extended content clipping can provide precise control over hidden content overflows visibility := visible | hidden | collapse | inherit in invisible state the element is still there you just can't see it it effects layout normally descendant of invisible element can be visible Outlines Like borders except: they don't cause reflow: good for adding an outline to emphasize focus they can be non-rectangular they can invert the background Syntax: outline := <outline-color> || <outline-style> || <outline-width> outline-width := thin | medium | thick | <length> only one (unlike borders with top bottom left right) outline-style := dotted | dashed | solid | double | groove |ridge | inset | outset outline-color := <color> | invert | inherit Tips separation of concerns HTML should describe structure don't use class names that describe style CSS should describe styling start with an inline style sheet after perfection move CSS code to an external sheet title attribute adds tooltips to images and links don't use div when you can use HTML tags classes vs ids classes for repeating elements id selectors for unique elements ids get priority margin: 0 auto lets content float equivalent to <center> margins collapse line-height creates implicit padding Workflow put temporary code on top of the stylesheet makes it easiest to work with firebug name classes by structure, not styling separation of concerns HTML for content structure CSS for styling refactor eliminate code CSS HTML let the future take care of itself use advanced selectors (instead of tons of classes) use more tag types when available not everything should be a div minimize reloads edit CSS mode better than editing on server copy to server at the end refactor in gvim debugging draw borders to better understand box model use two firebug windows one for selecting one for editing live Misc element types replaced vs non-replaced whether or not the content is included in the HTML most html tags non-replaced replaced tags img input tag block vs inline block by default fills its parent element can not have other elements at its sides I.e., generates a break before and after box e.g., p div li special case that generates marker inline generated line boxes that are flowed within parent internal style sheet <style type="text/css"></style> only in the head inline style sheets no time and bandwidth saving class names letters, numbers, hyphens and underscores must start with a letter case sensitive terminology ancestor descendent parent closest ancestor child closest descendent siblings inheritance not passed border properties placement properties margins paddings Specificity of CSS properties highest specificity wins weights tag selector = 1 class selector = 10 ID selector = 100 inline style = 1000 overruling specifiy !important after any prperty a { color: teal !important; } organizing styles and stylesheets name styles by purpose not appearance refactor common styles to separate classes combine multiple classes group styles apply to related parts ofa page group styles with related purpose xhtml differences from HTML lowercase tags quotation marks required for xhtml all tags must be closed <br /> validator.w3.org tags p # for paragraphs li dl # definition list dt # definition term blockquote # quotes q # one line quotes cite # referencing address # identify and supply contact info table tags caption attribute align=top|bottom colgroup col thead tr th tbody tr td cell properties text-align vertical-align top|baseline|middle|bottom border-collapse: collapse|separate [Less]
Posted over 15 years ago by Alon Swartz
Recently I needed to transfer data between entities, but I needed to keep the data secure from prying eyes, and its integrity intact from busy little fingers on the wire. I needed the solution to be simple, and support a high-performance ... [More] environment. Seeing that I could exchange a secret key over a secure channel out-of-band (OOB), I opted for using symmetric-key cryptography. Let me start off by saying that cryptography is a vast, fascinating and complex subject. I'll discuss some of the high-level key concepts related to the subject matter to provide some background, but thats about it. If you're interested, I recommend the above link as well as Applied Cryptography by Bruce Schneier.   What is symmetric encryption (and asymmetric for that matter) In a nutshell, symmetric-key cryptography refers to encryption methods in which both the sender and the receiver share the same key. This requires establishing a secure channel for secret key exchange, which also presents a considerable and practical chicken-and-egg problem. This is where asymmetric-key (or public-key) cryptography comes in.  Whitfield Diffie and Martin Hellman first proposed the notion of public-key cryptography in 1976, in which two different but mathematically interrelated keys (public and private) are used. The public key (freely distributed) is typically used for encryption, while the private key is used for decryption. Enough background for now, lets get to it!   Choosing the crypto library In my search for the most lightweight, flexible, powerful yet simple cryptographic Python library, I came across close to a dozen options.  After reading their documentation (cough!) and interfacing with their API's, I decided on python-crypto. The library has a wide collection of cryptographic algorithms and protocols, seemed like the best fit for what I was looking for, and is packaged by the major distributions. apt-get install python-crypto Next up, choosing the cipher Without going into detail, there are block ciphers and stream ciphers. They differ in how large a chunk of plaintext is processed in each encryption operation. A block cipher operates on a fixed-length group of bits (or blocks), for example 128-bits. In contrast, a stream cipher operates on relatively small blocks, typically single bits or bytes, and the encoding of each block depends on previous blocks. I chose to use a block cipher, in particular the Advanced Encryption Standard (AES), which has been adopted by the US government.   Finally, some example code from Crypto.Cipher import AES def encrypt(plaintext, secret) encobj = AES.new(secret, AES.MODE_CFB) ciphertext = encobj.encrypt(plaintext) return ciphertext def decrypt(ciphertext, secret) encobj = AES.new(secret, AES.MODE_CFB) plaintext = encobj.decrypt(ciphertext) return plaintext Because the plaintext needs to be a multiple of block size, we specify Cipher FeedBack (CFB) mode so we don't need to deal with padding. But, the secret too needs to be a valid block size (e.g., 16, 24, 32), so for ease of use, we can use a lazysecret to achieve this. def _lazysecret(secret, blocksize=32, padding='}'): if not len(secret) in (16, 24, 32): return secret + (blocksize - len(secret)) * padding return secret CRC (Cyclic redundancy check) As mentioned above, we need to verify data integrity, as well as perform a check that decryption with the provided secret key was successful. During encryption plaintext += struct.pack("i", zlib.crc32(plaintext)) During decryption crc, plaintext = (plaintext[-4:], plaintext[:-4]) if not crc == struct.pack("i", zlib.crc32(plaintext)): raise CheckSumError("checksum mismatch") In the above example, we are adding a 4 byte CRC of the data, onto the data, prior to encryption. After decryption, the CRC is recalculated and matched against the attached CRC. If they match, all is good in the world. If they don't, well, not good... Update: Thanks to tptacek on Hacker News for pointing out that a CRC is a non-secure hash function designed to detect accidental changes, and should not be used as a security check. Instead, it's recommended to use a secure hashing function such as SHA1. Putting it all together crypto.py import zlib import struct from Crypto.Cipher import AES class CheckSumError(Exception): pass def _lazysecret(secret, blocksize=32, padding='}'): """pads secret if not legal AES block size (16, 24, 32)""" if not len(secret) in (16, 24, 32): return secret + (blocksize - len(secret)) * padding return secret def encrypt(plaintext, secret, lazy=True, checksum=True): """encrypt plaintext with secret plaintext - content to encrypt secret - secret to encrypt plaintext lazy - pad secret if less than legal blocksize (default: True) checksum - attach crc32 byte encoded (default: True) returns ciphertext """ secret = _lazysecret(secret) if lazy else secret encobj = AES.new(secret, AES.MODE_CFB) if checksum: plaintext += struct.pack("i", zlib.crc32(plaintext)) return encobj.encrypt(plaintext) def decrypt(ciphertext, secret, lazy=True, checksum=True): """decrypt ciphertext with secret ciphertext - encrypted content to decrypt secret - secret to decrypt ciphertext lazy - pad secret if less than legal blocksize (default: True) checksum - verify crc32 byte encoded checksum (default: True) returns plaintext """ secret = _lazysecret(secret) if lazy else secret encobj = AES.new(secret, AES.MODE_CFB) plaintext = encobj.decrypt(ciphertext) if checksum: crc, plaintext = (plaintext[-4:], plaintext[:-4]) if not crc == struct.pack("i", zlib.crc32(plaintext)): raise CheckSumError("checksum mismatch") return plaintext   Interfacing with the above code couldn't be simpler. >>> from crypto import encrypt, decrypt >>> ciphertext = encrypt("confidential data", "s3cr3t") >>> print ciphertext \hzÛÍúXM~âD÷ð¿Bm >>> print decrypt(ciphertext, "s3cr3t") confidential data >>> print decrypt(ciphertext, "foobar") Traceback ... <class 'crypto.CheckSumError'>   Ever needed to use encryption in a Python project? Leave a comment! [Less]
Posted over 15 years ago by Liraz Siri
9 things I didn't know about CSS that I should have known years ago but I only picked up from a couple of good CSS books. Having dabbled in web development over the years, I've had a basic working knowledge of CSS for quite some time. In fact, I've ... [More] been around long enough to remember what the web was like when we were all using font tags and transparent pixel tricks. Back when it wasn't unusual to come across a web site using the BLINK tag. Let me tell you it was ugly and it was a mess. (Now get off my lawn!). As soon as browsers started supporting CSS I picked up just enough to save myself from committing the geek equivalent of a war crime, but I never got around to fully mastering CSS in all its glory. Advanced subjects such as floats and layout still seemed a bit mysterious. And every so often I would come across a bit of CSS code that made no sense yet rendered perfectly in every single browser I tested. Clearly my CSS skills were behind the times. <!--break--> Then a few months back I started working on a few improvements to the TurnKey web site and decided it was time to get back to basics. So I bought a couple of books which were recommended by a friend: CSS: The Missing Manual CSS: The Definitive Guide, 3rd edition If you need to pick just one I would say both were good but I think the definitive guide has an edge. It's better organized, more comprehensive, and a better reference. It also provides better "theory" that helps create a useful mental model of how things are supposed to work. OK, now on to the list: Learn how to use FireBug to test CSS on the fly: in hindsight, the most important thing I learned while reading these books and experimenting wasn't directly related to CSS itself - it was how to efficiently use FireBug to test CSS code on the fly. Previously I would write my CSS in a file text editor and then tweak the values in FireBug's inspection mode. I found myself hitting reload a lot and there was always a lag between writing CSS and seeing its effect on the web page. I found non-trivial tweaks to the CSS were much easier to write/experiment with in FireBug's "edit" mode, which just lets you mess around with the CSS in a simple editor and immediately applies those changes to the currently displayed browser window. In this mode you have to watch out not to hit reload or you will loose your CSS edits. After things are done, you can copy the result to a permanent file containing the stylesheet. Modern browsers (gasp) follow the rules: with regards to CSS itself the main thing I learned is that there are precise, non-browser specific rules governing web site presentation and lay out. Those of us who learned the ropes in earlier times when older browsers such as IE6 ruled have this misconception that browsers may interpret your CSS unpredictably. Modern browsers can be relied on to lay out your web site according to a rigorously defined, standard box model with rules that aren't so difficult to understand. What this means is that nearly all of the things I tried in Firefox 3.5 looked pretty much the same in IE7 and IE8. Down to the pixel level. And you may need that sort of pixel level control to implement visual effects such as rounded corners. Use the background Luke: the visual workhorse in CSS is the background family of properties: background-color # `transparent' is a color background-repeat # repeat-x repeat-y no-repeat background-image background-position "background" is a convenient short hand when you don't want to define background properties separately: background: <background-color> <background-image> <background-position> The primary limitation with the background property is that an element can only have one background. In some cases when that isn't enough you'll see designers inserting empty <div> hooks which are precisely positioned to create the illusion that a graphical element has multiple background (e.g., the round corners of fluid / variable-width element) Advanced selectors: CSS allows you more flexibility in selection than just the "standard" ancestor / descendant relationship: body h1 { # this matches any h1 element inside any other element inside # the body } You can also select direct children: body > h1 { # only h1 that is the direct child of body will match } Siblings: h1 + h2 { # only h2 that comes immediately after h1 will match } The first child of an element: ul li:first-child { # only matches the first li item } Global selector: * { # matches any element } *.myclass { # the better known .myclass is just shorthand } *#myid { # the better known #myid is just shorthand } Attribute selectors: img[title] select only img tags with "title" attribute input[type="text"] input fields of type text a[href][title] select a that has both href and title attrs *[title] any element that has title attribute img[title~="Figure"] any img with title that contains Figure in it regexp match? img[title^="bar"] any img with title that starts with "bar" img[title$="bar"] any img with title that ends with "bar" img[title*="bar"] any img with title that contains substring "bar" Things to remember about absolutely positioning elements They are taken completely out of the presentation flow. No space is made on the page for that element. They are positioned relative to the nearest absolutely or relatively positioned ancestor element (or otherwise the body). In other words, if you want to position element A relative to element B, you can put element A inside element B and define B as relatively positioned. You don't have to actually define an offset for the relative position of B. Margins collapse: margins are not just padding that goes beyond an element's borders. Margins collapse so that if the margins of two elements touch the smaller margin will collapse. They won't be accumulated! In other words if M1 > M2, M1 + M2 = M1 Any element can be turned into an inline or block element: display: inline|block Block elements and inline are elements are different in that blocks will insert a break and expand to the available in their parent box UNLESS THEY ARE FLOATED. By contrast, inline elements are happy to live side-by-side with other inline elements. The rules for floating is precisely defined by the standards. That's important because you should be able to rely on them down to the pixel to figure out in advance if an element will be floated along side an existing element or below it. You can forget about older broken browsers such as IE6 where you would sometimes get a broken result. The precise rules are a bit complex, but you don't really need to know them unless you need pixel perfect perfection. A few tips to help you get by: Floated elements are rectangle block boxes who's border dimensions are calculated to exactly fit their contents + padding + border. In other words, a float is as small as it has to be. Floats can float up and right but never up. So they'll never show up higher in the page than where they are inserted. In Firefox (tested up to 3.5) a parent element that contains floated elements doesn't expand to contain its floated children unless it's either also floated or has the "overflow: hidden" property. This confused me a bit as I didn't expect floated elements to spill out of the bottom of the containing element. Relative/absolute positioning is also rigorously defined. Once you know the rules you should be able to get predictable results. If you experiment in a modern browser you can expect the result to look the same in other modern browsers. Coming up next week: my CSS cheat sheet. [Less]
Posted over 15 years ago by Alon Swartz
So you're building a web application, and using the excellent contrib.auth subsystem to manage user accounts. Most probably you need to store additional information about your users, but how? Django profiles to the rescue! Django provides a ... [More] lightweight way of defining a profile object linked to a given user. The profile object can differ from project to project, and it can even handle different profiles for different sites served from the same database. In a nutshell, using Django profiles consists of 3 steps: Define a model that holds the profile information. Tell Django where to look for the profile object. Create the user profile as needed.   Defining the user profile model The only requirement Django places on this model is that it have a unique ForeignKey to the User model, and is called user. Other than that, you can define any other fields you like. For our example, we'll create 2 user profile fields (url and company). account/models.py from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) url = models.URLField("Website", blank=True) company = models.CharField(max_length=50, blank=True)   Tell Django about the profile object Accessing a users profile is done by calling user.get_profile(), but in order to use this function, Django needs to know where to look for the profile object. This is defined in the projects settings.py file. AUTH_PROFILE_MODULE = "account.UserProfile" Important note: The settings value is appname.modelname, and not appname.models.modelname as you might expect. The reason for this is that Django is not doing a direct import, but using an internal model-loading function. Once defined, and if the profile exists, accessing a users profile is simple. foo/views.py @login_required def view_foo(request): profile = request.user.get_profile() url = user_profile.url #OR url = request.user.get_profile().url   Create the user profile as needed Notice in the section above I mentioned "if the profile exists". This is because the get_profile() function will raise a DoesNotExist exception if the profile does not exist. One of the common solutions to this issue is to create the profile when a user is registered using a signal (see my post on Django Signals). Another option is catch the exception, and redirect the user to a profile creation form. You usually want to do this if the profile fields are mandatory. My personal favorite though, is to have the profile created automatically when referenced, with the added bonus of being able to reference a users profile as user.profile instead of user.get_profile() account/models.py ... class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) ... User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])   To reiterate, including the above enables us to reference the users profile with cleaner code, and have it created if it does not exist. foo/views.py @login_required def view_foo(request): url = request.user.profile.url   Ever needed to store additional user information? Post a comment! [Less]
Posted over 15 years ago by Liraz Siri
Ever tried logging into a machine with ssh and found you have to wait much longer than reasonable for the session to start? This happened to me a few times and was especially annoying with machines on my local network (or a VM attached to a virtual ... [More] network) that should be letting me in immediately. I eventually got mad enough to strace the SSH daemon and debug what was going on and it turns out it's a DNS thing. Basically the session is slow to start because the SSH server is trying to lookup the hostname of the SSH client and for whatever reason it's timing out (e.g., it can't reach a nameserver, because you happen to be offline) There are a couple of very simple ways to fix that: add "UseDNS no" to /etc/ssh/sshd_config add the client's net address to the server's /etc/hosts Was that helpful? Has this ever happened to you? Post a comment! [Less]