From 57e7bb546e0c14c6bea373b443789a1b88d0b495 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Tue, 11 Feb 2014 10:28:26 +0100 Subject: [PATCH] ncdc 1.18.1 + yxml manual + dcstats + minor restyle ...I need to commit more often. --- Bug.pm | 4 + dat/doc | 5 + dat/doc-dcstats | 222 +++++++++++++++++++++++++++++++ dat/ncdc | 12 +- dat/ncdc-changelog | 5 + dat/ncdc-install | 39 ++++-- dat/ncdu | 4 +- dat/yxml | 35 +++-- dat/yxml-man | 1 + download/ncdc-1.18.1.tar.gz.asc | 17 +++ download/ncdc-1.18.1.tar.gz.md5 | 1 + download/ncdc-1.18.1.tar.gz.sha1 | 1 + img/dcfiledist.png | Bin 0 -> 5981 bytes img/dcfilesize.png | Bin 0 -> 4519 bytes img/dclistcomp.png | Bin 0 -> 4869 bytes img/dclistsize.png | Bin 0 -> 5311 bytes img/dcnumfiles.png | Bin 0 -> 5028 bytes img/yxml-apistates.png | Bin 0 -> 23823 bytes index.cgi | 45 ++++--- style.css | 4 +- 20 files changed, 339 insertions(+), 56 deletions(-) create mode 100644 dat/doc-dcstats create mode 120000 dat/yxml-man create mode 100644 download/ncdc-1.18.1.tar.gz.asc create mode 100644 download/ncdc-1.18.1.tar.gz.md5 create mode 100644 download/ncdc-1.18.1.tar.gz.sha1 create mode 100644 img/dcfiledist.png create mode 100644 img/dcfilesize.png create mode 100644 img/dclistcomp.png create mode 100644 img/dclistsize.png create mode 100644 img/dcnumfiles.png create mode 100644 img/yxml-apistates.png diff --git a/Bug.pm b/Bug.pm index bcc2289..ffecc01 100644 --- a/Bug.pm +++ b/Bug.pm @@ -110,6 +110,10 @@ sub dbSave { # TODO: pagination / filtering sub htmlListing { my($s, $l, $lnk) = @_; + if(!@$l) { + p class => 'bug_nolisting', 'No bugs found! Yay?'; + return; + } table class => 'bug_listing'; thead; Tr; td class => 'bug_col_id', 'Id'; diff --git a/dat/doc b/dat/doc index 7aa6136..b9f1c76 100644 --- a/dat/doc +++ b/dat/doc @@ -6,6 +6,11 @@ rare occasions are published on this page. =over +=item C<2014-01-09 > - L + +The report of a short measurement study on the file lists obtained from a +Direct Connect hub. Lots of graphs! + =item C<2012-02-15 > - L In this article I explain a vision of mine, and the results of a small research diff --git a/dat/doc-dcstats b/dat/doc-dcstats new file mode 100644 index 0000000..672fcbd --- /dev/null +++ b/dat/doc-dcstats @@ -0,0 +1,222 @@ +Some Measurements on Direct Connect File Lists + +=pod + +(Published on B<2014-01-09>.) + +=head1 Introduction + +I've been working on Direct Connect related projects for a while now. This +includes maintaining L and +L, and doing a bit of research into +improving the downloading performance and scalability (to be published at some +later date). Whether I'm writing code or trying to setup experiments for +research, there's one thing that helps a lot in making decisions. Measurements +from an actual network. + +Because useful measurements are often missing, I decided to do some myself. +There's a lot to measure in an actual P2P network, but I restricted myself to +information that can be gathered quite easily from file lists. + + +=head1 Obtaining the Data + +Different hubs will likely have totally different patterns in terms of what is +being shared. In order to keep this experiment simple, I limited myself to a +single hub. And in order to get as much data as possible, I chose the hub that +is commonly known as "Ozerki", famous for being one of the larger hubs in +existence. + +My approach to getting as many file lists as possible from this hub was perhaps +a bit too simple. I simply modified ncdc to have an "add the file list from all +users to the download queue" key, and to save all downloaded lists to a +directory instead of opening them. + +I started this downloading process on a Monday around noon when there were a +little over 11k users online. I hit my hacked download-all-filelists-key two +more times later that day in order to get the file lists from those users who +joined the hub at a later time. I let this downloading process running until +the evening. + +One thing I learned from this experience was that the downloading algorithm in +ncdc (1.18.1) does not scale particularly well. Every 60 seconds, it would try +to open a connection with B users listed in the download queue. You can +imagine that trying to connect to 11k users simultaneously put a significantly +heavier load on the hub than would have been necessary. Not good. Not something +a well-behaving netizen would do. Surprisingly enough, the hub didn't seem to +mind too much and handled the load fine. This might have been because Mondays +are typically not the most busy days in P2P land. Weekends tend to be busier. + +Despite that scalability issue, I successfully managed to download the file +lists of almost everyone who remained online for long enough to finally get +their list downloaded. In total I managed to download 14143 file lists (that's +one list too many for C<10000*sqrt(2)>, I should have stopped the process a bit +earlier). The total bzip2-compressed size of these lists is 6.5 GiB. + +For obvious reasons, I won't be sharing my modifications to ncdc. I already +tarnished the reputation of ncdc enough in that single day. If you wish to +repeat this experiment, please do so with a scalable downloading +implementation. :-) + + +=head1 Obtaining the Stats + +And then comes the challenge of aggregating statistics on 6.5 GiB of compressed +XML files. This didn't really sound like much of a challenge. After all, all +one needs to do is decompress the file lists, do some XML parsing and update +some values. Most of the CPU time in this process would likely be spent on +bzip2 decompression, so I figured I'd just pipe the output of L to a +Perl script and be done with it. + +To get the statistics on the sizes and the distribution of unique files, a data +structure containing information on all unique files in the lists was +necessary. Perl being the perfect language for data manipulation, I made use of +its great support for hash tables to store this information. It turned out, +rather unsurprisingly, that Perl isn't all that conservative with respect to +memory usage. Neither my 4GB or RAM nor the extra 4GB of swap turned out to be +enough to run the script to completion. I tried rewriting the script to use a +disk-based data structure, but that slowed things down to a crawl. Some other +solution was needed. + +When faced with such a problem, some people will try to optimize the algorithm, +others will throw extra hardware at it, and I did what I do best: Optimize away +the constants. That is, I rewrote the data analysis program in C. Using the +excellent L hash table library +to keep track of the file information and the equally awesome +L library (a little bit of self-promotion +doesn't hurt, right?) to do the XML parsing, I was able to do all the necessary +processing in 30 minutes using at most 3.6GB of RAM. + +Long story short, here's my analysis program: +L. + + +=head1 A Look at the Stats + +Some lists didn't decompress/parse correctly, so the actual number of file +lists used in these stats is B<14137>. The total compressed size of these lists +is B<6,945,269,469> bytes (6.5 GiB), and uncompressed B<25,533,519,352> bytes +(24 GiB). In total these lists mentioned B<197,413,253> files. After taking +duplicate listings in account, there's still B<84,131,932> unique files. + +And now for some graphs... + +=head2 Size of the File Lists + +Behold, the compressed and uncompressed size of the downloaded file lists: + +[img graph dclistsize.png ] + +Nothing too surprising here, I guess. 100 KiB seems to be a common size for a +compressed file lists, but lists of 1 MiB aren't too weird, either. The largest +file list in this set is 34.8 MiB compressed and 120 MiB uncompressed. The +uncompressed size of a list tends to be (*gasp*) a bit larger, but we can't +easily infer the compression ratio from this graph. Hence, another graph: + +[img graph dclistcomp.png ] + +Most file lists compress to about 24% - 35% of their original size. This seems +to be consistent with L done in 2010. + +The raw data for these graphs is found in +L, which lists the +compressed and uncompressed size, respectively, for each file list. The gnuplot +script for the first graph is +L and +L for the +second. + +=head2 Number of Files Per List + +So how many files are people sharing? Let's find out. + +[img graph dcnumfiles.png ] + +As expected, this graph looks very similar to the one about the size of the +file list. The size of a list tends to be linear in the number of items it +holds, after all. + +The raw data for this graph is found in +L, which lists the +unique and total number of files, respectively, for each file list. The gnuplot +script is +L. + +=head2 File Sizes + +And how large are the files being shared? Well, + +[img graph dcfilesize.png ] + +This graph is fun, and rather hard to explain without knowing what kind of +files we're dealing with. I'm not going to do any further analysis on what kind +of files these file sizes represent exactly, but I am going to make some +guesses. The files below 1 MiB could be anything, text files, images, +subtitles, source code, etc. And considering that the hub in question doesn't +put a whole lot of effort in weeding out spammers and bots, it's likely that +some malicious users will be sharing small variations of the same virus within +the 100 KiB range. The peak of files between 7 and 10 MiB would likely be +audio files. The number of files larger than, say, 20 MiB drop significantly, +but there are still a few million files in the 20 MiB to 1 GiB range. + +I cut off the graph after 10 GiB, but there's apparently someone who claims to +share a file between 1 and 2 TiB (don't know the exact size due to the +binning). Since I can't imagine why someone would share a file that large, I +expect it to be a fake file list entry. Note that there could be more fakes in +my data set. I can't tell which files are fake and which are genuine from the +information in the file lists, but I don't expect the number of fake files to +be very significant. + +The "raw" data for this graph is found in +L. Because I wasn't +interested in dealing with a text file of 84 million lines, the data is already +binned. The first column is the bin number and the second column the number of +unique files in that bin. The file sizes that each bin represents are between +C<2^(bin+9)> and C<2^(bin+10)>, with the exception of bin 0, which starts at a +file size of 0. The source of the gnuplot script is +L. + +=head2 Distribution of Files + +Another interesting thing to measure is how often files are shared. That is, +how many users have the same file? + +[img graph dcfiledist.png ] + +Many files are only available from a single user. That's not really a good sign +when you wish to download such a file, but luckily there are also tons of files +that I available from multiple users. What is interesting in this graph +isn't that it follows the L, +but it's wondering what those outliers could possibly be. There's a collection +of 269 files that has been shared among 831 users, and there appears to be a +similar group of around 510-515 files that is shared among 20 or so users. I've +honestly no idea what those collections could be. Well, yes, I could probably +figure that out from the file lists, but my analysis program doesn't tell me +which files it's talking about and I'm too lazy to fix that. + +The graph has been clipped to 600, but there's another interesting outlier. A +single file that has been shared by 5668 users. I'm going to guess that this is +the empty file. There are so many ways to get an empty file somewhere in your +filesystem, after all. + +The raw data for this graph is found in +L, which lists the +number of times shared and the aggregate number of files. The gnuplot script is +L. + + +=head1 Final Notes + +So, erm, what conclusions can we draw from this? That stats are fun, I guess. +If anyone (including me) is going to repeat this experiment on a fresh data +set, make sure to use a more scalable downloading process that I did. My +approach shouldn't be repeated if we wish to keep the Direct Connect network +alive. + +Furthermore, keep in mind that this is just a snapshot of a single day on a +single hub. The graphs may look very different when the file lists are +harvested at some other time. And it's also quite likely that different hubs +will have very different share profiles. It could be interesting to try and +graph everything, but I don't have I kind of free time. + diff --git a/dat/ncdc b/dat/ncdc index 702db5b..0e1973d 100644 --- a/dat/ncdc +++ b/dat/ncdc @@ -10,14 +10,14 @@ ncurses interface. =item Latest version -1.18 ([dllink ncdc-1.18.tar.gz download] +1.18.1 ([dllink ncdc-1.18.1.tar.gz download] - L - L) Convenient static binaries for Linux: -L<64-bit|http://dev.yorhel.nl/download/ncdc-linux-x86_64-1.18.tar.gz> - -L<32-bit|http://dev.yorhel.nl/download/ncdc-linux-i486-1.18.tar.gz> - -L. Check the +L<64-bit|http://dev.yorhel.nl/download/ncdc-linux-x86_64-1.18.1.tar.gz> - +L<32-bit|http://dev.yorhel.nl/download/ncdc-linux-i486-1.18.1.tar.gz> - +L. Check the L for more info. =item Development version @@ -45,6 +45,7 @@ C - If the mailing list is too slow for you. Are available for the following systems: L - +L - L - L - L - @@ -55,6 +56,9 @@ L I also have a few packages on the L. +An convenient installer is available for +L. + =back =cut diff --git a/dat/ncdc-changelog b/dat/ncdc-changelog index 4a67d9e..ca40060 100644 --- a/dat/ncdc-changelog +++ b/dat/ncdc-changelog @@ -1,3 +1,8 @@ +1.18.1 - 2013-10-05 + - Fix crash when downloading files from multiple sources + - Use the yxml library to parse files.xml.bz2 files + - Fix various XML conformance bugs in parsing files.xml.bz2 files + 1.18 - 2013-09-25 - Add support for segmented downloading - Support $MyINFO without flags byte on NMDC hubs diff --git a/dat/ncdc-install b/dat/ncdc-install index 664533c..17e75a9 100644 --- a/dat/ncdc-install +++ b/dat/ncdc-install @@ -38,11 +38,11 @@ compiling and/or installing it, I also offer statically linked binaries: =over -=item * L +=item * L -=item * L +=item * L -=item * L +=item * L =back @@ -58,6 +58,12 @@ architecture, please bug me and I'll see what I can do. =head1 System-specific instructions +=head2 Android + +An L is +available for Android 2.3 and later, which makes use of the static binary. + + =head2 Arch Linux Ncdc is available on L, to @@ -70,6 +76,15 @@ favorite, go for the manual approach: makepkg -si +=head2 Fedora + +There's a L +available for Fedora. + +Alternatively, I also have packages on the L. + + =head2 FreeBSD @@ -115,9 +130,9 @@ First install some required packages (as root): Then, fetch the ncdc source tarball, extract and build as follows: - wget http://dev.yorhel.nl/download/ncdc-1.18.tar.gz - tar -xf ncdc-1.18.tar.gz - cd ncdc-1.18 + wget http://dev.yorhel.nl/download/ncdc-1.18.1.tar.gz + tar -xf ncdc-1.18.1.tar.gz + cd ncdc-1.18.1 export PATH="$PATH:/usr/perl5/5.10.0/bin" ./configure --prefix=/usr LDFLAGS='-L/usr/gnu/lib -R/usr/gnu/lib' make @@ -165,9 +180,9 @@ required libraries: Then run the following commands to download and install ncdc: - wget http://dev.yorhel.nl/download/ncdc-1.18.tar.gz - tar -xf ncdc-1.18.tar.gz - cd ncdc-1.18 + wget http://dev.yorhel.nl/download/ncdc-1.18.1.tar.gz + tar -xf ncdc-1.18.1.tar.gz + cd ncdc-1.18.1 ./configure --prefix=/usr make sudo make install @@ -209,8 +224,8 @@ website|http://cygwin.com/> and use it to install the following packages: Then open a Cygwin terminal and run the following commands to download, compile, and install ncdc: - wget http://dev.yorhel.nl/download/ncdc-1.18.tar.gz - tar -xf ncdc-1.18.tar.gz - cd ncdc-1.18 + wget http://dev.yorhel.nl/download/ncdc-1.18.1.tar.gz + tar -xf ncdc-1.18.1.tar.gz + cd ncdc-1.18.1 ./configure --prefix=/usr make install diff --git a/dat/ncdu b/dat/ncdu index 1997d0d..af3e746 100644 --- a/dat/ncdu +++ b/dat/ncdu @@ -41,7 +41,7 @@ notifications for new releases. =head2 Packages and ports -Ncdu has been packaged for quite a few systems already, here's a list of the ones I am aware of: +Ncdu has been packaged for quite a few systems, here's a list of the ones I am aware of: L - L - @@ -68,7 +68,7 @@ L Packages for CentOS, RHEL and (open)SUSE can be found on the L. -Packages for NetBSD, DragonFlyBSD, MirBSD and others and be found on +Packages for NetBSD, DragonFlyBSD, MirBSD and others can be found on L. diff --git a/dat/yxml b/dat/yxml index a5dfa7b..e39484c 100644 --- a/dat/yxml +++ b/dat/yxml @@ -11,14 +11,15 @@ The code can be obtained from the L and is available under a permissive MIT license. The only two files you need are L and L, which can easily be -included and compiled as part of your project. Minimal documentation is -included in yxml.h, more complete documentation is pending. +included and compiled as part of your project. Complete API documentation is +available in L. -The API follows a simple, mostly buffer-less design and only consists of two -functions: +The API follows a simple and mostly buffer-less design, and only consists of +three functions: - void yxml_init(yxml_t *x, char *stack, size_t stacksize); + void yxml_init(yxml_t *x, void *buf, size_t bufsize); yxml_ret_t yxml_parse(yxml_t *x, int ch); + yxml_ret_t yxml_eof(yxml_t *x); Be aware that I is not necessarily I or I. The API is relatively low-level and designed to integrate into pretty much any application @@ -28,11 +29,9 @@ devices. It is possible to implement a more convenient and high-level API on top of yxml, but I'm not very fond of libraries that do more than what I strictly need. -Yxml is still in a beta stage and hasn't been very thoroughly tested yet. There -are no tarball releases available at the moment. The API and ABI may still -change a bit, so I strongly advise against dynamic linking (I'm not sure if -I'll ever promise a stable ABI, but the API should certainly get stabilized at -some point). +There are no tarball releases available at the moment. The API is relatively +stable, but I won't currently promise any ABI stability. Dynamic linking +against yxml is therefore not a very good idea. =head3 Features @@ -95,11 +94,11 @@ using C<< >>. =back These conformance issues are the result of the byte-oriented and minimal design -of yxml, and I do not intent to fix these directly within the library. All of -the above mentioned issues can be fixed on top of yxml (by the application, or -by a wrapper) if strict conformance is required. With the exception of custom -entity references, but I have a simple idea on how to support that in the -future, too. +of yxml, and I do not intent to fix these directly within the library. The +intention is to make sure that all of the above mentioned issues can be fixed +on top of yxml (by the application, or by a wrapper) if strict conformance is +required, but the required functionality to support custom entity references +and DTD handling has not been implemented yet. =head3 Non-features @@ -136,7 +135,7 @@ implementation is also included as an indication of the "theoretical" minimum. expat 2.1.0 MIT 162 139 194 432 1.47 1.09 libxml2 2.9.1 MIT 464 328 518 816 2.53 1.75 mxml 2.7 LGPL2+static 32 733 75 832 12.38 7.80 - yxml git MIT 5 935 31 384 1.14 0.74 + yxml git MIT 5 971 31 416 1.15 0.74 The code for these benchmarks is available in the L directory on git. Some @@ -177,7 +176,7 @@ with C<-Os> than with C<-O2>. expat 2.1.0 MIT 113 314 145 632 1.58 1.20 libxml2 2.9.1 MIT 356 948 412 256 3.01 2.08 mxml 2.7 LGPL2+static 27 725 71 704 11.70 7.44 - yxml git MIT 4 835 30 264 1.72 1.05 + yxml git MIT 4 955 30 392 1.67 1.02 =head2 Validating vs. non-validating @@ -204,6 +203,6 @@ It should be noted that a lot of XML documents found in the wild are not described with a DTD, but instead use an alternative technology such as XML schema. Wikipedia L on this. -Using a validating parser for such documents would only introduce bloat and may +Using a validating parser for such documents would only add bloat and may introduce L. diff --git a/dat/yxml-man b/dat/yxml-man new file mode 120000 index 0000000..e3d28a5 --- /dev/null +++ b/dat/yxml-man @@ -0,0 +1 @@ +../../yxml/yxml.pod \ No newline at end of file diff --git a/download/ncdc-1.18.1.tar.gz.asc b/download/ncdc-1.18.1.tar.gz.asc new file mode 100644 index 0000000..c1c87d4 --- /dev/null +++ b/download/ncdc-1.18.1.tar.gz.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.20 (GNU/Linux) + +iQIcBAABCgAGBQJSUBb8AAoJEGI5TGmMJzn6wlAQANWirjw2yB5MLBVJlj5WfCOH +ky6giyilDJnn8C2PPOXmvI8ddTUm6OSNCpGrK2gQ82bUqurx10aIYQfy+GZHvSgj +5pi8GIQiQ1Js4b9BdX54zgeE6GhCk10mN0R4+xoMgszN+5mwRrg66WGsF2A6dZiB +vvm3rQnpk3ydDb9kn/vGun8CT9e2xX43aXZ4EJtheHXkdx+o76Pb7LmORElZnKqm +10Dw+SGZQ272xuiwnj1UROvMUnbs8yhq8ADpRONL7L1UGlORUpFjmAkB3UE8kLFE +4CjTgYLKG6X3L8CFRMttQWmGNTMuvCBxGjqASUQunC1HV10B87ItbuHIiNbjxsEB +pj+6dGye4gSI7J3piAXrIe4PG27UhQ9BnbQbhv7NtVM9IPSlb3hyMjzqZOethnRX +PgTdwdEy53TI50hJf8tZAC8ZEOyPKtxFqufm7dx8NgoVsX0Si6NLwaAEpxu4h/Ny +2QSWB3zGFZinaQ0QWuvXbzJMqjyzYvXGDpPGCUaGx4vcdE/Rz85ywzYeuBIiEH24 +N7NFD+nVaIpRQthH7GRqOwzgn1qHFPvm6DDj+jv3gzpUSkOz16iWVcIyatXPFJg1 +BFvlaZm8e2/lQXEyTu8QW6soGq4Pp+nxvow7xpMBSKNAk9gw7GBRPn1TaDQaD83t +BLtM/ZkDdqrJMqQnWq9n +=CwkC +-----END PGP SIGNATURE----- diff --git a/download/ncdc-1.18.1.tar.gz.md5 b/download/ncdc-1.18.1.tar.gz.md5 new file mode 100644 index 0000000..0050749 --- /dev/null +++ b/download/ncdc-1.18.1.tar.gz.md5 @@ -0,0 +1 @@ +c0070916c8bb8a0409d01f6663ca0c6a ncdc-1.18.1.tar.gz diff --git a/download/ncdc-1.18.1.tar.gz.sha1 b/download/ncdc-1.18.1.tar.gz.sha1 new file mode 100644 index 0000000..d020dcf --- /dev/null +++ b/download/ncdc-1.18.1.tar.gz.sha1 @@ -0,0 +1 @@ +184dce59b5b51563f869a43d81971a1537cdc438 ncdc-1.18.1.tar.gz diff --git a/img/dcfiledist.png b/img/dcfiledist.png new file mode 100644 index 0000000000000000000000000000000000000000..018bac20d0ddd01e4fdb3232c4ceafceb4f4e590 GIT binary patch literal 5981 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 KwCt!`?0*0ZQdl+s literal 0 HcmV?d00001 diff --git a/img/dcfilesize.png b/img/dcfilesize.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6b1e5e01ffee10fff5f937469890acded8d098 GIT binary patch literal 4519 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 RCXuyC6TF2{z9BjEe*jNsk}UuL literal 0 HcmV?d00001 diff --git a/img/dclistcomp.png b/img/dclistcomp.png new file mode 100644 index 0000000000000000000000000000000000000000..c5b7fc922addcf0da10a76233c8f43eb2bdfbb92 GIT binary patch literal 4869 zcmai1c{r5s*B_!ZLdm`jiqecFvab<}EU6g#GTE9eS(9ZZ8Hy26(-&C_#Uzg*`&Jn{ zp^!CMqREW4Nhb3?>ig@xe*e7hT+j8)x$imW+~<7Ga-X?tZE4B{6@fw^5Uz7)&)7g9 ztVjriC6!|jxMNJAmVgUo>+_e4nM@|Qlb4sb`_%%0V3{otCWK0DF@SV*Ku-J4Fk2)c zSc4WUQ^^gR1c4Y}Axtb2!+c+O;shva@aY{WCn6%EqM~A9Vd3TFg~4DlGBQXcQcFuq zPfySM{5*KXin4MlHTA{l!ph~9PfR9tGM4$O^(B?c9D#tRL9T#rjC7K;LXzF@b&{}f zAZQ8%(wopnf$W;dg!BzC`O=vf>lG}PX$<*^4O$}HTv@<3R-a^01Q3LI^dM z`T#OCnKzkgZEzW_h~@+3wzM!of0!-3)j2E7 zmAqHIt<2Wmmhvd3K^{}Gsi`S9Hx~wjO;1lZH#fVwy6WreQ~6|CA&^7&&Yd}Z>Bi&b zY)(SyiG#-TlkQi7Vm>p9S6E}TMfSuOu+d%UvS9_q*EHp2VoE@~|LgPKN0dIiS@eAQ z%w&TVByQ+CxhXW-F?86}Z>UkW?gN{Fh9X4+)fnZ8c~)ZjEAv@y>3(eBdAp1cR!`oH z#i+6zv~+xd_Z)g5HS1sndF*kLu>7lMBO_v)R}%kGdzthac`*5-wpG?;@o?PUMB^T0 zpPg%3_>8#FnoK88;&QN1g@}o;MCtyIiyeY+eV$aU`0E2R6&rwB_YIlrUfZ!I6&^w zHt%$lKuIZrG^?(Xz#S}L5Lb}=Fr1K9twT0+0crM|pavGyEe>N*I1M2a5P`=vfHda@ zsDYKtdMHuNcFNvtYE6hU0;B~NZvh5u;IVvu#0JuXhWV2MYaoqyw+GY!9(#NYnLBg` z!+mn=_?$e(4%MqDy>_9)vB?J&Et?2@g8Vi3K5D7cG++!E{qaf?XXpvV7aoJv`?h<` zj*HCJw~?2iNiso0mTlx}RdRSzGK%PNccStlu`_{{ zX$KNKOQen532e;a@KrBPmR-0e2AahwOc5y#(KE6;ZZU8yU;j4nwDmWb((QvF^1T1? zC%(*D{wg<9g}54yMNg5{P|xsuGKaIdQoipHkCkB5RnI# zO-M1FTAQ*!!;4=fpR6+52zCPzrWGwyMtVXon{K`it$*!mMW2wM6-6(XYYmxvf32F_ zcF{=s(_|%in6ToShwib4{0w?1r-Khwg5UTYK&+$WDn@Qhdq)rGjgMfKJ!Z2`eKul- z4I(3sown-)uA;6Lt~CA9^1l2cvE#Xb=(GqLqlf2*; z_5;73*1X58sFJO+VOqF3rM9K?ONfz+m&1)54Sro-A-Hfp`71-Tbj<9NBSUn!_Yp1+^v?l#J2WqZ=}b$>|N0PQhqi5in!Sv*YfG>GFo)IuB~? z7uUXd6f`W((y;xW#D4rke5CWb<-LdJB~X6)WaJ^RLPQs#=`$mhUOF!XgSd~oY}^nN zMi(2%lC^juiA%HU;o?2q5@3DhiNP5$ZyM6`%;%6^#y=N}Tfy`&rU7biK^(Ba3A_vo zxkPW;Dh24f2!<_~XqAe}-iH#${$Bsf^|_ZD&d7QdtwwgvBl7BUgV;=2jH`yCzmY~VIla`xAKBT_}N|X_!`^)RL(v( z;yUOS7YNg*_zyQoZ=lUZ$=V1J5nTz;s+~wg<6^NCSYz~4w#k6b+-zEPgLnRZG9Y;% zpOrPU02IHXG!b}88<%ed`Ww>=G$GQ%c|-1s!G{)w%&lBXe8+cKAIkl9TvF9wEZnHk z@WY=hiQ9XYQs-dDv^nu7fYJi7HHocr6Yc|;FAYEq zdh@`}v3!-NFrx=zl=Z7W2LMRcNZAswS6i_GW-XvWa|*C zV4)@~`1)wO85|bkySAYp{ih``b#0wJojKCWl;qttZOJ&LleP}8??F}IakYCwg-2gA=Se&hn4FuBQQ=8L$Ps%es_hbdDW|4<;`Tm9|57;cb#E01L` z@uF7l9D9f3RJ|`colXKvX6W*N=9?#+^pobgB88|^yCvJ8`&mrac1w|fPwfXzvDlF z1sF%4U4e0s&E$g*gX2Jh7}`#jcJz)IMF#{OyxRXT*>q2^;U79I$b#d*9~E3=C^(M% ztHM(#h6jRL^5wS}ASY&_{3_QhV>^Jp+kf(o!#ST7R95PvM98rn_>Ttuz2vp0|Ix5f znYi~~`9J-{-3?)ts5bn6i=I&x7&*3m3n-IBO4?YAZ_?Q1_}~|vT*?jNGG9@~OGtV) z@@hM|*8Q6SX@cPN170`Ab9E-Qqdzc)+XDDa@qwZbFYS(BMQ9jQ_>P17V23cO@b#k= zI~{iDK;ku{jLUt;y$i1)o{M#_Dy|T=Z65R(`I;B6QkbHo`!BZ^U`f? z-=lgnnUssQcDqxiMscrY&p4g})#QIOj_UQC_cU-Ubv9xhlq@Nnm%A zK>a$ZsL8koD2VAAyBcF^_K~}!O=8@L)2Kjp1~)kLxrfOg1Y=n+knS=P3rrpVh)nyO z<+hQ4X+_$bHYfVsl4_oFx}%rVyfD0JPLWZy)n;p%R*)Q8i;(F+K62caR2q)36rv~s z^S4`&?pNNAJ0ZmJoMao>>dj4dl-#YGTQvXA93`V>yk z+dGO?2vMGi(sik-7ZfNq(is3RpJ;yo1v9hpL0wP@rHqm}uI5q!gsnJOCto3(S-%V< z$>1=W*SC!Jh(|2HL(UQ-0v_Yo+Q>;Nw#RevRgc-2+MDMV{C1WHrO_DPnap?f&Fk|H zF36bved|8tZGo|G2UDCjI?>&anqU4p=ONOqK3n6|?P|T#Ez9W139y67h2yLd&+%1R z4SN_}{=jvt>qmJt?iH2D;*h_8Q_4~%I&4Q$x;&(=9yvDMRTfRRS$;Yk+DNrGS6ruQWHvz3m@T#Uv#Wz z@ti}KjwQbM6{U*BGP;fWkfcf{QJ7?OJ0r?FT=V@5e zY;f^hr|2V8sE6n?HS+t1qhpE%CJo6vwxe#iq&iYSnUH*?v z)ZQvj9CVy|9@hAv0X^?|>c}g`)tZ_7kkfS&ZC#TgZxwFnZYUdwI8K$+%{iM)%_CoF zKf3SAmHNs-@M#hkU45PFY>+n}o7ECWZfctDqzCWYzv%xZu!F0Oesh3+@UhTC^g#QP z)E_S8OX1ra9XP$!$<^?g+bnHr)%A<2AGnr^zUKC#YS?y$jtIWpiSzGk0_MKUsZ9lj z+q0hkpx1-C(bLv$sxYz0^7Uoo#>%^tDc$7u(Z(?PO@JOT2AiP14N3mxn3Xe%3fQUQ zw4iy}Psz_x4}~7!)N_I9j$f?_obp@u^{?LBpS`J3E#0kxo4`@2UTtBuOTqTlsXjZc zncgalK^Se!%quwbn?xNoA$)t9?}y}{1atNW+YOD-DA)as7Zl_7 zlXL>FC=FNoOAWBb%170y=zYwO)4Et3K-O-1B=14sX_r@-w%GZGuD)JO?}?AHXlZclFb`YT*%^WpVhxPCk3 zK?PctJyWC_|NC+QWHjITCqTNM3Su+-q_PN<$Hs0;*RhQOT8| zq=u{yxwL!0#KAroN|mB(OA2{Zuf+ma#++O}zMC5`H+t$Fs(&*bExFMmzRKJY? z$I)mFPdOApm#dAq^R>5vkpoPaH>wTmRC{&+Q^T_pi9N38eXVqLqn~f1h`T}B)gVzD z2t$2*lc{ft`~D_^bNo$qt;+R;)6@&r-!XoKaFSkACi}wOoq@60?MJve-)kOUo|Q*y zTWXWQ(7ZX6C0uEt%WdD6DK)^j{X*!`gig?mo+&O2-?{vp;%>b_6Ub>2Q+H6$$+)4K zF1nI2_1mm(B$3Ga?i)SAou{g^VyMLSTK5Y2>f51-3*y(>R^EKS&q)_< z*E(uZv^1dm)c!u(fd8qrm@@_688Kz$e5mVXfsz*@W2Pqxg_24||5S+qmdPT#P{0WFEYx&iH5C}y*Z1;0-rp4_KbaLg+OquRtO8iV6+-RIy)i8-d|X) zNC?iT6~|I{!zDl^5g8P!|G=ii!l|$s(D+%V6es@pf$)faEz8skX1{#^!GgB z@ZlRE6$qp^u5S^-rpSWy4X}h$S<$wuI2_9yvV#knC*EG2eb`j%`{o|s#>V6`9FkQ8 zVZ<=fAVX8nrjl)q9DI-BgdsR#VVn_o;&5)QI5!rK&EJUi3_RUf&u*||^z?K~ON*mS+Z$WWM=03P9cv4iInZIBFYI)p~{>z=`hz$_%xg1u#&Jo;&V= z6{h*nc0i6)EGg}xw8Bd}ycwx$rQ)raN}imF*-vOgwfSz~Ive6CIC9C6@p;=PjRNZh z%L~vHtcW`llX7J#hJW4&t>L$zzWs2^u-@^zM(OiR1o1@b*{7wBXrmJdQ8y^SfhrLp zCR%aoI7%T=hfm0$o^itx9!0;H3HWrt2F!%Ej%jS!>jFJyQ!Eopo)^qJD+BmRt zrH&i;>o_ll&Y6G1G=qE#f}ub$yJc8UBr2Uo_Y&)*toAtMG5L(G8KQ zkw1&x9C^8gLJCU(4l0$>(#}u5-6OxT@`$rUtF0QNsYdA9BT+&m6=h+kJwJR>^LE2l zb$M3H6<6lL-AAlJt6f6I?Si=%+IK=|Ph{6DXpzZ{N={dc#SbksCP4F75dj#=Nccfc zdgvXK9tlOa&UM^4)rYZtk{Aa8NOcL2NXV84-`4(yL zYcN%TcoP}Set$dwG@XHBKoIxZJDmdvB4j0L4m~it$Mjq)7MMYkXfmWO9w@@mAQyI# zorEL~Af6K#f4qSYhn>S=izO1m9HH#&llCJV57Uyu{*p@jpktD6wsOV@ZDxeNf<(y< z!})YZXJR3sc?A0kOOV8y$RbHc5Tb&JQBha|tQt_!pu%-?@e&Cm5f1=eZr}oa_dY3q zHSJfqg;!j8U&Ppo@7?dpa1M;%Tl=}D#fh>i-9g7W{Y5(D>y?e;e}{i3(z&prPw$7o z@fo!JY<;ykp-5H+CHn@XXxxgmyp9Y-D&ojy?x zYRe(}=zZxec4)aeH}&-vVJ3%5ex<5?Q{U>cclmmvtp!&qS+_Q}?B@s===*L$j>nzX zp8q!0MU2Y$2$;xGcNR`bi0F)((qvF`*|SCp`1Zs~+px2nhj=mmDRsOaH48#8--I4( zvv8#GN61J-Jy2p!8S)J z)(43S00<7)U8dZtJ?5FijZ7r9-t2s$gSdNteWv3*gQclCZ_Lz{XB-&1v7K^{*p)P` zF%Aqj2c}&xweiZht2I~wC;uXhSPG7Q(-}Qt*hzU6p7~&QV|QqnCUBRmW+zL^5U31$ zar&~K-RM=m$6H27(#c^dyp8E6;)T(x3FEOJIw@)csqU6~u>Bb4f-~rrD1=zPI{#Yi z2lpIoi|GB50_6Lew8~kh5&@H>5ZdkhPNr@k_@*B3#V#s-q^N+;z+r|XpZ zNcfhj*?SccFsR8#N%LNXu0xw|z^20rc+3^$7Le+QWNY6J4yw$^jo!aTCG_uaMM-<8 zCZGS)5j`L(gSvnusb~mmjD;takMChO7zgN+Z99U)>u+XVHc#y-Hug1K{;^TDdD>!4 zYAY{sCI?ZhPjsc}pUc7G0Y7!#?xQQYMSTrD-A)~xm|js2i9x$J#{7041*-XWGlEcG z_s2-63LqR0A&BZLaMMm1I1`HT?`md?B&}LcG>d-|RrdN3B|s3LK@fIfwAaoTYddJ3 zKNztRi$eN3MCU>;Qgdb478uw8IaJk71dVAed@tElcvJ39lEYCY`%^2sig0bVV!NQW1qI-ofY7Wn2Bu?%F$6pA)8A0z zmY6geGg3H!t=M!~3T#h>P6~qqbi+&)XmSDyumRNN(>s@y8PKmP}; zTQ0(I819?uuAqJG#GjhfcpKUD8T3^n^n(-8=h4pY_u7lk4+kh42_Ao3JrE4(N%QDd(>@);KUXZDYu~5iS_%u;ztqcS`!V zX4eqrnxgNBKalISd}jEVM}*=nkvob%8>3CuY-}((qa`Jbi48c<}1 zX7kk7OPD|)TI6xWmPI!u_q}E%9sS~dHwBF&3;Dlau5-e?Oc6)CNtpNK1^hLhmqV*lZ<~fJaOl3LKOcO@-0dPUXPgl$8vcNbua}4 zzvslKU%wd8F9>&#tDUo|7B6XXmBWVBrA(}UBt(Uvm;dnjpU`BNhH_S8c?J}MQJoYU zYau}`V<)=)^8?YP1s9Q|i>YQ@f#c(5BLUYVb_$R!SL|nnm-E&4R5tU{deY;clh*ed z%sp%d)JWGC>YWa{6qc^5VTG$?uofBkk=jKbvm#j$7k(j~(Mt;@wjZr@L_Kn_u8}$|$K3VnloTrFgPlA)Zt?~psu~n0e@9AnLHP?x?!E5H5Bg-fgMU&> zijKV9T;8Z%yZ9f6g~r0qB+@^jkko~O$5`#U4;!yTz(t_n6AJja9HV@&iL0NmT86}EXoMBENfU~bJKO|3D1nfWVvI{K^KmYTn&kBECVaEPC zQ{dLl!T;qVdaef#)}|;DMM9>7RO}jJG-0rA(`@qdmjN&iU=5*!g3?kz<=@J^;=xKr z3W?f9Y7y8Ac|0i-^(-6r6Qw>)Pn1LLF~`5dn&k1*tajiI!_rM zWBWZNlJpBdvN^gb$Btprl6$)nskypFx^$f%6Mjuv^#rEL*Nd5QA*GXYD!!Mp)Z8^5 z^}J6HPrs=~ihIS;CXcH1)u@V`4Vr`zq&_9t9Ov!kHh`&06X1)fZVtxz$;EvUU=qIt zR*K@3TwS!PNK+dHr^x|fxm(8J(b zcmqj-CA$+QP`cEDO@0hv0#BATQr^dtug(Eem4K=KGtQvDoJesuhx|W*?zoZ&&WRC(V78G| zS@HvkZXQ6Ee3?Y9k8B zo`@>6mk&a5WVO$ti8XZ&U|>KEugQKt8|)JGyp%PaK4ImVI=3DIKGW$2m>&&pGL2K* zutoo>GVu^vFfq7a1_jSke3Q!Rqy0(>KniT-UpwjSeU3H)SN)Y5S6Hr0^_gx<8+pVw z_~KD8X5dx7M>aBKvSeLNms%!%yk}seqi<6z;#59!GUImG-~>x)NGo(~Qj2liVV8H` z=DDHW-yJvZnBd52f(j(hy_Z7K7D{u2n}KbZB+2338-Xm6t;=S|`?j)f$*bxs?+3Hw=Crf59{bIB;nTnB&v7wpzkFXDiQL^=$}-SBHnnQKUe>{Ny(lxcnK^FhQ=d0|ND77+rMsD+OSxd( zevDol^vLGhZ2m^WOyh>h{y>S|<(z&$7wb?HG?bY4||ult+v+1+xksm2~r_CjvHcglm(26k1A=tci^nH4f%D`&GoBb!0u&)qrj~= zhZpU5q5@vzvvZL03^Pa!Mu371XETOy6paegAN|u%5p`F`@pQ5~cUTs>NOqnvO@ ztnH!CyJL6-H>pLTbl|b0oiMNl(q_6IQKAYVNzKN_1&mi%?KM-y1Yc|FG&^;^9QrW~PvCJyPdTBP>0Nr5 zx=Vzk)&_)=r%lk}p+M!i`(tbbjrUyJ;LJrN%BE(2S??LuEGwT{jc_H@{&T74?~?!E z>TC3p=r$V*RhJ<_VF@3qeK6byxx2cO;N1ld=r3R?%f2$c`!7cY4Q4Uw{+iGs;92>^rrfCh1Sk~ zU$QBFu^`Amy_T;zVqG0E7+61B`OW61xVA9iRd!uyaIRbYtD4!)rM}|cu=(*58@Jv? zQiqmuH?zv>mToc3S}>-9-+eT-E3#}}H)x;nz#j8IEmv`AoVcc&du^+6+N_sOy%ik7 zA1^mvSQkETUNF_9qtY-^_U+qF;k(BIQPhh|EwZ5}B8#)$JroXJ|BGVQ5D{!2 zTJAu7vEbx=<^4)n{8U2Jkmi=)y&o^9&E`Kpt~?BH&NWJL$6~rDu+;h7f#uwd zEK=QXtJ01H&zobRW{;P1_ovuYrU@-Ui4&9dVwxpX|3K zFK_!A+XeNzBO^Gf=BV_s=`7UZX?OqcmVp#5)1%?%t0Hn6m1?m|VH2bmYlA&6#WOs& zUQgTi(!D;-*S|{!CL05Erx+a)`BOggzZ#-1nE~UP>RpWRmIt5~S=3{<>(;%C#Y4*h zJ%ZyeiHTTG2fS+UWbs|g(0-=%@YN_sU;$PvkzG2K|AebSJQ&Y*d%CL7K6v7f;*U+= zwXK7p|H|OMZgCOA9k0vV;8y%OS4$KUxYMz3&aV5OP2wIJ`ysr1`*R>1Gm{{3p`WyZr}5E#iWa?5^_V-DvYq;E zMaW(S5UL__s_A;(SRRkHHY2_Gpx+Uqw{FzBHKYazsHC% jU+NIo&G>gzT92+8!bS2;U1N{iup?w?Ze#Y!#4YAOJ|-(E literal 0 HcmV?d00001 diff --git a/img/dcnumfiles.png b/img/dcnumfiles.png new file mode 100644 index 0000000000000000000000000000000000000000..563fcfa82b5c6ed32d5c0b94a36f44d7596bb591 GIT binary patch literal 5028 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

SW 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 sub { changelog(shift, 'tuwf-changelog', 'TUWF', 'tuwf', 'changes', 'TUWF Changelog') }, qr{ylib} => sub { podpage(shift, 'ylib/README.pod', 'ylib', '', 'Ylib') }, qr{yxml} => sub { podpage(shift, 'yxml', 'yxml', '', 'Yxml - A small, fast and correct* XML parser') }, + qr{yxml/man} => sub { podpage(shift, 'yxml-man', 'yxml', 'man', 'Yxml Manual', 1) }, qr{doc} => sub { podpage(shift, 'doc', 'doc', '', 'Articles') }, qr{doc/sqlaccess} => sub { podpage(shift, 'sqlaccess', 'doc', '', 'Multi-threaded Access to an SQLite3 Database', 1) }, qr{doc/commvis} => sub { podpage(shift, 'doc-commvis', 'doc', '', 'A Distributed Communication System for Modular Applications', 1) }, + qr{doc/dcstats} => sub { podpage(shift, 'doc-dcstats', 'doc', '', 'Some Measurements on Direct Connect File Lists', 1) }, qr{dump} => sub { podpage(shift, 'dump', 'dump', '', 'Code dump') }, qr{demo} => sub { podpage(shift, 'dump-demo', 'dump', 'demo', 'Demos') }, qr{dump/awshrink} => sub { podpage(shift, 'dump-awshrink', 'dump', 'awshrink', 'AWStats Data File Shrinker') }, @@ -112,10 +117,10 @@ TUWF::register( qr{dump/nccolour} => sub { podpage(shift, 'dump-nccolour', 'dump', 'nccolour', 'Colours in NCurses') }, qr{dump/insbench} => sub { podpage(shift, 'dump-insbench', 'dump', 'insbench', 'Insertion Performance Benchmarks') }, qr{(?:($feedreg)/)?feed\.atom} => \&atom, - qr{(ncdc|ncdu|globster)/bug} => \&bug_list, - qr{(ncdc|ncdu|globster)/bug/post} => \&bug_post, - qr{(ncdc|ncdu|globster)/bug/new} => \&bug_new, - qr{(ncdc|ncdu|globster)/bug/([1-9][0-9]*)} => \&bug_item, + qr{(ncdc|ncdu|globster|yxml)/bug} => \&bug_list, + qr{(ncdc|ncdu|globster|yxml)/bug/post} => \&bug_post, + qr{(ncdc|ncdu|globster|yxml)/bug/new} => \&bug_new, + qr{(ncdc|ncdu|globster|yxml)/bug/([1-9][0-9]*)} => \&bug_item, ); TUWF::set( @@ -195,7 +200,7 @@ sub atom { my $n = 0; for(@changes) { - next if $sub && $_->[1] !~ /^\/\Q$sub/; + next if $sub && (!$_->[1] || $_->[1] !~ /^\/\Q$sub/); last if $n++ >= 10; tag 'entry'; tag id => 'http://dev.yorhel.nl'.($_->[1]||'/').'#'.$_->[0]; @@ -420,7 +425,7 @@ sub genChanges { sub htmlHeader { my $s = shift; my %o = ( - spec => { map +($_,1), qw|ncdu ncdc globster tuwf| }, + spec => { map +($_,1), qw|ncdu ncdc globster tuwf yxml| }, page => '', sec => '', sec2 => '', @@ -440,17 +445,15 @@ sub htmlHeader { div class => 'notes'; txt 'Yoran Heling'; br; a href => 'mailto:projects@yorhel.nl', 'projects@yorhel.nl'; - br; a href => 'http://yorhel.nl', 'yh'; - txt ' - '; a href => 'http://g.blicky.net', 'git'; - txt ' - '; a href => 'http://pgp.mit.edu:11371/pks/lookup?search=0x8c2739fa', 'pgp'; - br;br; - lit q| -

- - - - -
|; + br; a href => 'http://yorhel.nl', 'home'; + txt ' - '; a href => 'http://g.blicky.net', 'git repos'; + br; b '= donate ='; + a href => 'https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=BBF8LGT2LLNFN&lc=US¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted', 'paypal'; + txt ' - '; a href => 'bitcoin:1PhXZaKbPFhuz4KbRcfUL9VveB58psa8R', 'bitcoin'; + br; b '= pgp ='; + a href => 'http://yorhel.nl/key.asc', 'key'; + txt ' - '; a href => 'http://pgp.mit.edu:11371/pks/lookup?search=0x8c2739fa', 'mit'; + br; i '7446 0D32 B808 10EB A9AF A2E9 6239 4C69 8C27 39FA'; end; img id => 'scissors', src => '/img/scissors.png', alt => 'Cute decorative scissors, cutting through your code.'; end 'div'; @@ -523,14 +526,18 @@ sub htmlMenu { $m->('/tuwf/man/xml', '::XML', $o{sec} eq 'man' && $o{sec2} eq 'xml'); }); $m->('/tuwf/changes', 'Changelog', $o{sec} eq 'changes'); + } elsif($o{page} eq 'yxml') { + $m->('/yxml', 'Info', !$o{sec}); + $m->('/yxml/man', 'Manual', $o{sec} eq 'man'); + $m->('/yxml/bug', 'Bug tracker', $o{sec} eq 'bug'); } else { $m->('/', 'Home', !$o{page}); $m->('/ncdu', 'Ncdu '); $m->('/ncdc', 'Ncdc '); $m->('/globster', 'Globster '); $m->('/tuwf', 'Tuwf '); + $m->('/yxml', 'Yxml '); $m->('/ylib', 'Ylib', $o{page} eq 'ylib'); - $m->('/yxml', 'Yxml', $o{page} eq 'yxml'); $m->('/doc', 'Articles', $o{page} eq 'doc'); $m->('/dump', 'Code dump', $o{page} eq 'dump', sub { $m->('/dump', 'Misc.', $o{page} eq 'dump' && !$o{sec}); diff --git a/style.css b/style.css index 2db9953..f6b5a1d 100644 --- a/style.css +++ b/style.css @@ -19,8 +19,10 @@ html,body { background: #ccc; text-align: center; height: 100% } #left li a.small { font-size: 10px } #left .menusel { color: #03a } #left .notes { margin-top: 50px; text-align: center } -#left .notes, #left .notes a { font-size: 9px; text-decoration: none } +#left .notes, #left .notes a, #left .notes b { font-size: 9px; text-decoration: none } #left .notes a:hover { text-decoration: underline } +#left .notes i { font-size: 7px; display: block; margin-top: -2px; margin-bottom: -10px; font-style: normal } +#left .notes b { display: block; margin-top: 10px; margin-bottom: 2px } #scissors { position: relative; top: 30px; left: 113px; } img.right { float: right; margin: 0 0 5px 10px } .indexgroup { margin: 30px 10px 0px 20px }